完整版见https://jadyer.github.io/
这是一个Struts2.1.8.1应用,代码如下
首先是web.xml文件
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <welcome-file-list> <welcome-file>anonymity.jsp</welcome-file> </welcome-file-list> </web-app>
然后是用于提交匿名访问的页面anonymity.jsp
<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <%-- <%session.setAttribute("user", "玄玉");%> --%> <s:form action="anonymity" theme="simple"> 当匿名用户点击Submit提交请求时,即Session中没有用户的登录信息时<br/> 会由于自定义的AuthInterceptor拦截器的生效而自动跳转到LOGIN页面<br/> <s:submit value="我要匿名访问"/> </s:form>
用于显示给匿名用户的anonymityLogin.jsp页面
<%@ page pageEncoding="UTF-8"%> <h2>匿名用户访问应用时</h2> <h2>便自动跳转至该页面</h2>
用于显示给合法用户的anonymitySuccess.jsp页面
<%@ page pageEncoding="UTF-8"%> <h2>Visit Success</h2>
然后是struts.xml文件
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd"> <struts> <package name="anonymous" extends="struts-default"> <interceptors> <interceptor name="auth" class="com.jadyer.interceptor.AuthInterceptor"/> </interceptors> <!-- 注意:不同包package之间不能互相访问对方的全局结果。除非两个包是继承关系才可以使用父包的global-results --> <!-- 于是可以把某些公用的东西放到一个继承了struts-default的包中,然后大家去继承这个包,就可以轻松实现信息共享 --> <global-results> <result name="login" type="redirect">/anonymityLogin.jsp</result> </global-results> <action name="anonymity" class="com.jadyer.action.AnonymityTestAction"> <result name="input">/anonymity.jsp</result> <result name="login">/anonymityLogin.jsp</result> <result name="success">/anonymitySuccess.jsp</result> <interceptor-ref name="auth"/> <interceptor-ref name="defaultStack"/> </action> </package> </struts>
然后是在Struts2中自定义的监听器类MyListener.java
package com.jadyer.listener; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.PreResultListener; /** * 实现PreResultListener的自定义监听器 */ public class MyListener implements PreResultListener { public void beforeResult(ActionInvocation invocation, String resultCode) { System.out.println("result : " + resultCode); //resultCode是一个类似于input、success的值 } }
然后是在Struts2中自定义的拦截器类AuthInterceptor.java
package com.jadyer.interceptor; import java.util.Map; import com.jadyer.listener.MyListener; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; /** * 拦截匿名用户的自定义拦截器 * @see 使用Servlet过滤器可以拦截所有资源或某个目录,而拦截器则只能拦截某个请求或某一类请求 * @see 所以在开发的时候,应该根据具体情况,选择使用Servlet过滤器或者自定义Struts2的拦截器 */ @SuppressWarnings({"serial", "unchecked"}) public class AuthInterceptor extends AbstractInterceptor { public String intercept(ActionInvocation invocation) throws Exception { String result = "input"; invocation.addPreResultListener(new MyListener());//注册监听器 System.out.println("------AuthInterceptor invoked begin------"); //这里getSession之后得到的是一个Map,不是HttpSession //但是这个Map的底层依然是由HttpSession来维护的 //当然也可以使用ActionContext.getContext().getSession()获取Map类型的session Map map = invocation.getInvocationContext().getSession(); if (null == map.get("user")) { result = Action.LOGIN; //若用户未登录,则转到登录页面 } else { result = invocation.invoke(); //若用户已经登录,则继续执行 } System.out.println("------AuthInterceptor invoked finish------"); return result; } }
最后是用到的Action类
package com.jadyer.action; import com.opensymphony.xwork2.ActionSupport; /** * 继承ActionSupport之后,如果不重写execute()的话,它默认的会返回"success" */ @SuppressWarnings("serial") public class AnonymityTestAction extends ActionSupport {}
后记:亦可在web.xml中设定<security-constraint>标签属性
后记:使得特定资源需要经过Tomcat认证之后方可访问
后记:示例代码如下
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- ******【以下是访问需要Tomcat认证的资源时的配置信息】****** --> <!-- 也就是类似于我们在http://127.0.0.1:8080/页面点击Tomcat Manager时弹出的认证输入框 --> <!-- 如果在认证输入框中连续输入三次错误的用户名和密码的话 --> <!-- IE浏览器就会直接报告HTTP Status 401 - ,即用户验证失败,不允许继续访问 --> <!-- FF浏览器就不会报告任何错误,而是一直弹出认证输入框,供用户输入用户名和密码 --> <!-- 除非在Firefox的认证对话框,点击取消按钮,才会显示401 Unauthorized提示 --> <security-constraint> <web-resource-collection> <web-resource-name>my website auth</web-resource-name> <!-- 指定需要认证的目录。这里设定的是对根下面的test下面的所有信息进行认证 --> <!-- 也就是说当访问struts.xml中命名空间为/test下面的所有资源时都需要认证 --> <url-pattern>/test/*</url-pattern> <!-- 指定需要认证的访问方式。这里设定的是对点击表单提交或点击链接等方式发送过来的访问都进行认证 --> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <!-- 指定权限。这里的权限名取值自下面的<security-role/>标签中的<role-name/>值 --> <role-name>admin</role-name> </auth-constraint> </security-constraint> <security-role> <!-- 指定哪些组的用户可以访问,这里设定的是只有admin组的用户可以访问 --> <!-- 我们在Tomcat6.0.20//conf//tomcat-users.xml中的配置信息如下 --> <!-- <user username="jadyer" password="75" roles="admin,manager"/> --> <!-- 所以在运行该例子时,在弹出的提示框中需要输入的用户名和密码为jadyer和75 --> <role-name>admin</role-name> </security-role> <login-config> <!-- 设定认证方式。共有四种,这里用的是最简单的认证方式 --> <!-- 这种方式速度最快,但不安全,因为此时用户名和密码均以明文的形式保存在Tomcat配置文件中了 --> <auth-method>BASIC</auth-method> <!-- 这个realm-name的名字可以随便起,它是显示给用户的提示信息。但遗憾的是好像不能传递中文 --> <realm-name>Import Data,Please input AdminInfo</realm-name> </login-config> </web-app> <!-- 下面是相关的struts.xml配置 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="security" extends="struts-default" namespace="/test"> <action name="security" class="com.jadyer.action.SecurityTestAction"> <result>/login.jsp</result> </action> </package> </struts> --> <!-- 下面是相关的JSP页面的访问代码 <%@ page pageEncoding="UTF-8"%> <br/> <br/> <input type="button" value="访问需要认证的资源" οnclick="javascript:window.location='<%=request.getContextPath()%>/test/security.action';"/> -->