由于最近在负责公司项目的权限这一块,整个项目用到s2sh,所以自然想到了用struts2的拦截器作为登录和进行权限验证的接口
首先来谈谈struts2的实现原理:
Struts2拦截器是在访问某个Action或Action的某个方法,字段之前或之后实施拦截,并且Struts2拦截器是可插拔的,拦截器是AOP的一种实现.
Struts2拦截器的实现原理相对简单,当请求struts2的action时,Struts 2会查找配置文件,并根据其配置实例化相对的 拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器。
struts2给我们提供的拦截有很多,但是所有struts2的拦截器都直接或者接着的实现了com.opensymphony.xwork2.interceptor.Interceptor。
这里我们会用到com.opensymphony.xwork2.interceptor.AbstractInterceptor
这里我只需要覆盖他的intercept(ActionInvocation invocation)这个方法就可以了
下面是A自定义AuthorInterceptor 的代码:
import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.Action; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; public class AuthorInterceptor extends AbstractInterceptor { IAuthService authService; public void setAuthService(IAuthService authService) { this.authService = authService; } @SuppressWarnings("unchecked") @Override public String intercept(ActionInvocation invocation) throws Exception { // 获得拦截到的action名称 String actionName =invocation.getInvocationContext().getName(); ActionContext ctx = invocation.getInvocationContext(); Map session = ctx.getSession(); HttpServletRequest request = (HttpServletRequest)ctx.getContext().get(ServletActionContext.HTTP_REQUEST); //如果拦截到的action是请求登录的action,则放行. if("login".equals(actionName) || "logout".equals(actionName)){ return invocation.invoke(); }else{ Op op = (Op)session.get("currentUser"); if(op==null){ return Action.LOGIN; } String url = request.getRequestURI(); //判断该用户有无访问该路径的权限 boolean status = authService.interceptPermission(op.getOpId(), url); if(status){ return invocation.invoke(); }else{ session.put("errorsInfo", "您没有该资源的权限!"); return Action.ERROR; } } } }
拦截器在struts.xml中的配置需要注意:下面有说明:
<package name="BasePackage" extends="struts-default"> <interceptors> <!-- 声明自己的拦截器,起名叫check,对应的class属性为自己编写的拦截器路径 --> <interceptor name="check" class="authorInterceptor" /> <!-- 定义拦截器栈,这里需要注意:在定制自己拦截器的同时,必须要把struts的默认栈加如里面,如果不加入,相当于把默认的覆盖了,会出现异常! --> <interceptor-stack name="myCheck"> <interceptor-ref name="check" /> <interceptor-ref name="defaultStack" /> </interceptor-stack> </interceptors> <!-- 定义默认拦截器 --> <default-interceptor-ref name="myCheck" /> <!-- 定义全局结果,用于在拦截器中返回登录页面或者错误提示页面 --> <global-results> <result name="login" type="redirect">/login.jsp</result> <result name="error">/error.jsp</result> </global-results> </package> <!-- 登录的action --> <package name="default" namespace="/" extends="BasePackage"> <action name="login" class="loginAction"> <result>/index.jsp</result> <result name="input" type="redirect">/input.jsp</result> </action> <action name="logout" class="loginAction" method="logout"> <result type="redirect">/login.jsp</result> </action> </package>
public class LoginAction extends ActionSupport{ //service层 private IAuthService authService; public String execute(){ HttpServletRequest request = (HttpServletRequest)ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST); HttpSession session = request.getSession(); Op op = this.authService.Login(request.getParameter("opName"),request.getParameter("pwd")); if(op==null){ return Action.INPUT; } session.setAttribute("currentUser", op); //获得用户的菜单列表形成tree List<Resource> listRes = this.authService.findResources(op.getOpId()); session.setAttribute("listRes ", listRes ); return SUCCESS; } public String logout(){ HttpServletRequest request = (HttpServletRequest)ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST); HttpSession session = request.getSession(); session.removeAttribute("currentUser"); return SUCCESS; } public void setAuthService(IAuthService authService) { this.authService = authService; }