摘要说明:
项目中经常这样的需要
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 ...) {
//添加用户的实现代码
}
}
当前端发出/agent2/user/add的请求的时候,拦截器LogInterceptor和AgentAuthInterceptor会依次拦截请求执行自己的操作,LogInterceptor拦截器会用日志记录用户的信息以及请求的参数,返回true,交给AgentAuthInterceptor拦截器,AgentAuthInterceptor拦截器会判断响应请求的方法是否有@AgentAuthCheck注解同时authRequired属性是否为true,如果都有,那么执行鉴权操作,鉴权成功则返回true,响应请求的方法addUser执行,鉴权失败则返回false,请求不继续执行。