摘要说明:
项目中经常这样的需要
1. 登陆鉴权:比如用户浏览器发出某个请求的时候我们需要判断这个用户是否已经登陆,也就是cookie中是否有他的登陆信息。
2. 访问日志记录:用户访问请求的时候我们有必要记录访问者的身份信息以及访问了哪个url,请求参数是什么,这个请求的耗时是多少等等。
我的项目中是通过如下方法实现的。先贴上代码,再逐步讲解原理。
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true" scanPeriod="60 seconds" debug="false"> <contextName>jweb_wb_mgmt</contextName> <property name="path" value="/data/jweblog/jweb_wb_mgmt_beta"/> <!-- 控制台 --> <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>[%date{HH:mm:ss.SSS}] [%thread] [%-5level] [%logger{36}] %msg%n</pattern> </encoder> </appender> <!-- 访问日志 --> <appender name="access" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${path}/access/access.%d{yyyy-MM-dd}.log </fileNamePattern> <maxHistory>3</maxHistory> </rollingPolicy> <encoder> <pattern>[%date{HH:mm:ss.SSS}] [%thread] [%-5level] [%logger{36}] %msg%n</pattern> </encoder> </appender> <!-- 访问日志 --> <logger name="access" level="DEBUG" additivity="false"> <appender-ref ref="access"/> </logger> <root level="INFO"> <appender-ref ref="console"/> </root> </configuration>
spring-mvc.xml定义拦截器如下 【springMVC拦截器的讲解请查看这里】
<mvc:interceptors> <bean id="logInterceptor" class="com.zjr.common.web.interceptor.LogInterceptor"/> <bean id="agentAuthInterceptor" class="com.zjr.common.web.interceptor.AgentAuthInterceptor"/> </mvc:interceptors>
package com.zjr.common.web.interceptor; // import .... public class LogInterceptor extends HandlerInterceptorAdapter { Logger logger = LoggerFactory.getLogger("access"); long beginTime; /** * Log the request entrance */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { beginTime = System.currentTimeMillis(); Map<String, Cookie> cookies = HttpUtils.getCookies(request.getCookies()); String userId = String.valueOf(cookies.get("userId") != null ? cookies.get("userId").getValue() : request.getHeader("userId")); String token = String.valueOf(cookies.get("token") != null ? cookies.get("token").getValue() : request.getHeader("token")); String agentUserId = String.valueOf(cookies.get("agentUserId") != null ? cookies.get("agentUserId").getValue() : request.getHeader("agentUserId")); String agentUserToken = String.valueOf(cookies.get("agentUserToken") != null ? cookies.get("agentUserToken").getValue() : request.getHeader("agentUserToken")); //记录请求的用户信息 logger.info("Request URI:{} userId:{} token:{} agentUserId:{} agentUserToken:{}", request.getRequestURI(), userId, token, agentUserId, agentUserToken); if (logger.isDebugEnabled()) { StringBuilder sb = new StringBuilder(); for (String key : request.getParameterMap().keySet()) { sb.append(key).append(":").append(request.getParameterValues(key)[0]).append(";"); } //记录请求参数 logger.debug("Request URI:{} data:{}", request.getRequestURI(), sb); } return true; } /** * Log the request finished 记录整个请求所花费的时间 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { logger.info("Request URI:{} Cost:{}", request.getRequestURI(), (System.currentTimeMillis() - beginTime) + "ms"); } /** * Log the request exit */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } }
AgentAuthCheck.java【自定义的注解@AgentAuthCheck】
package com.zjr.common.web.auth; //import ... /** * 代理登录鉴权注解 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AgentAuthCheck { /** * 是否需要用户鉴权 */ boolean authRequired() default false; }
AgentAuthInterceptor.java拦截器 【登陆鉴权】
package com.zjr.common.web.interceptor; //import ... public class AgentAuthInterceptor extends HandlerInterceptorAdapter { private static Logger logger = LoggerFactory.getLogger("access"); @Autowired private Agent2UserBiz agent2UserBiz; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 用户登录鉴权判断 if (handler instanceof HandlerMethod) { // 获取鉴权设置 HandlerMethod method = (HandlerMethod) handler; AgentAuthCheck agentAnnotation = method.getMethodAnnotation(AgentAuthCheck.class); if (agentAnnotation != null && agentAnnotation.authRequired()) { String agentUserId = BaseWebservice.getValueFromHeaderOrCookie(request, "agentUserId"); agentUserId = agentUserId == null ? null : URLDecoder.decode(agentUserId, "utf-8"); String agentUserToken = BaseWebservice.getValueFromHeaderOrCookie(request, "agentUserToken"); Agent2User user = agent2UserBiz.checkLogin(agentUserId, agentUserToken); if (user != null) { AgentThreadData.setAgent2User(user); logger.info("AuthInterceptor checkLogin success. URI:{} agentUserId:{} agentUserToken:{}", request.getRequestURI(), agentUserId, agentUserToken); } else { BaseWebservice.setCookie(response, "agentId", "", 0); BaseWebservice.setCookie(response, "agentUserId", "", 0); BaseWebservice.setCookie(response, "agentUserName", "", 0); BaseWebservice.setCookie(response, "agentUserToken", "", 0); BaseWebservice.responseJson(response, BasicResult.createFailResult(ErrorType.LOGIN_AUTH_ERROR), 200); logger.warn("AuthInterceptor checkLogin fail. URI:{} agentUserId:{} agentUserToken:{}", request.getRequestURI(), agentUserId, agentUserToken); return false; } } } return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { AgentThreadData.removeAgent2User(); } }
package com.zjr.modules.agent2.webservice; //import ... @RestController @RequestMapping(value = {"/agent2/user"}) public class Agent2ShopService { //登陆不需要鉴权 @RequestMapping(value = "/login") public BasicResult login(@RequestParam ...) { //用户登录的实现代码 } //添加用户请求需要鉴权 @AgentAuthCheck(authRequired = true) @RequestMapping(value = "/addUser") public BasicResult addUser(@RequestParam ...) { //添加用户的实现代码 } }