Spring REST和Spring MVC实现登录拦截
记录一下 Spring Rest和Spring MVC结合实现的管理系统,登录是怎样解决的
由于Spring 的AOP面向切面编程,与Servlet容器没有任何关联,所以想要获得Session会话比较麻烦
具体思路和代码:
1、保存request和session的类 SysContent.java
package com.dmefx.dmeadmin.utils; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; public class SysContent { private static ThreadLocal<HttpServletRequest> requestLocal= new ThreadLocal<HttpServletRequest>(); private static ThreadLocal<HttpServletResponse> responseLocal= new ThreadLocal<HttpServletResponse>(); public static HttpServletRequest getRequest() { return (HttpServletRequest)requestLocal.get(); } public static void setRequest(HttpServletRequest request) { requestLocal.set(request); } public static HttpServletResponse getResponse() { return (HttpServletResponse)responseLocal.get(); } public static void setResponse(HttpServletResponse response) { responseLocal.set(response); } public static HttpSession getSession() { return (HttpSession)((HttpServletRequest)requestLocal.get()).getSession(); } }
2、配置过滤器 CorsFilter.java
/** * Title: 跨域访问处理(跨域资源共享) * Description: 解决前后端分离架构中的跨域问题 * @author Victor */ public class CorsFilter implements Filter { /** Log4j日志处理(@author: victor) */ private static final Logger log = Logger.getLogger(UserController.class); private String allowOrigin; private String allowMethods; private String allowCredentials; private String allowHeaders; private String exposeHeaders; public void init(FilterConfig filterConfig) throws ServletException { allowOrigin = filterConfig.getInitParameter("allowOrigin"); allowMethods = filterConfig.getInitParameter("allowMethods"); allowCredentials = filterConfig.getInitParameter("allowCredentials"); allowHeaders = filterConfig.getInitParameter("allowHeaders"); exposeHeaders = filterConfig.getInitParameter("exposeHeaders"); } /** * @description 通过CORS技术实现AJAX跨域访问,只要将CORS响应头写入response对象中即可 * @author Victor * @param req * @param res * @param chain * @throws IOException * @throws ServletException * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) */ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) res; String currentOrigin = request.getHeader("Origin"); log.debug("currentOrigin : " + currentOrigin); if (StringUtil.isNotEmpty(allowOrigin)) { List<String> allowOriginList = Arrays .asList(allowOrigin.split(",")); log.debug("allowOriginList : " + allowOrigin); if (CollectionUtil.isNotEmpty(allowOriginList)) { if (allowOriginList.contains(currentOrigin)) { response.setHeader("Access-Control-Allow-Origin", currentOrigin); } } } if (StringUtil.isNotEmpty(allowMethods)) { response.setHeader("Access-Control-Allow-Methods", allowMethods); } if (StringUtil.isNotEmpty(allowCredentials)) { response.setHeader("Access-Control-Allow-Credentials", allowCredentials); } if (StringUtil.isNotEmpty(allowHeaders)) { response.setHeader("Access-Control-Allow-Headers", allowHeaders); } if (StringUtil.isNotEmpty(exposeHeaders)) { response.setHeader("Access-Control-Expose-Headers", exposeHeaders); } SysContent.setRequest((HttpServletRequest) req); SysContent.setResponse((HttpServletResponse) res); chain.doFilter(req, res); } public void destroy() { } }
3、使用AOP进行环绕通知切入所有com.dmefx.dmeadmin.controller包下的所有类的方法
package com.dmefx.dmeadmin.aspect; import java.lang.reflect.Method; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import com.dmefx.dmeadmin.annotation.IgnoreSecurity; import com.dmefx.dmeadmin.authorization.TokenManager; import com.dmefx.dmeadmin.exception.TokenException; import com.dmefx.dmeadmin.utils.Constants; import com.dmefx.dmeadmin.utils.SysContent; import com.dmefx.dmeadmin.utils.WebContextUtil; /** * Title:安全检查切面(是否登录检查) * Description: 通过验证Token维持登录状态 * * @author Victor */ @Component @Aspect public class SecurityAspect { /** Log4j日志处理(@author: victor) */ private static final Logger log = Logger.getLogger(SecurityAspect.class); private TokenManager tokenManager; @Resource(name = "tokenManager") public void setTokenManager(TokenManager tokenManager) { this.tokenManager = tokenManager; } @Around("@annotation(org.springframework.web.bind.annotation.RequestMapping)") public Object execute(ProceedingJoinPoint pjp) throws Throwable { // 从切点上获取目标方法 MethodSignature methodSignature = (MethodSignature) pjp.getSignature(); log.debug("methodSignature : " + methodSignature); Method method = methodSignature.getMethod(); log.debug("Method : " + method.getName() + " : " + method.isAnnotationPresent(IgnoreSecurity.class)); // 若目标方法忽略了安全性检查,则直接调用目标方法 if (method.isAnnotationPresent(IgnoreSecurity.class)) { return pjp.proceed(); } // 从 request header 中获取当前 token String token = WebContextUtil.getRequest().getHeader( Constants.DEFAULT_TOKEN_NAME); // 获取session HttpSession session = SysContent.getSession(); HttpServletResponse response = SysContent.getResponse(); String username = (String) session.getAttribute(Constants.DEFAULT_SESSION_NAME); if (username == null) { // 不符合条件的,跳转到登录界面 response.sendRedirect("toLogin.do"); } // 检查 token 或 username 有效性 if (!tokenManager.checkToken(token) && username == null) { String message = String.format("token [%s] is invalid", token); log.debug("message : " + message); throw new TokenException(message); } System.out.println("我还在执行吗"); // 调用目标方法 return pjp.proceed(); } }
追崇技术,乐在分享!

浙公网安备 33010602011771号