在实际项目中,我们往往会发放一个 token
凭证给前端,前端在每次请求的时候通过请求参数或者请求头将 token
传给后端进行验证。后端在获得 token
,验证通过之后会将 token
转成实际需要的参数,比如 userId
。
在 SrpingBoot
项目中,由于在请求参数中并没有 userId
这个参数,所以我们无法通过方法形参获取到 userId
,因此我们需要通过 HttpServletWrapper
来将 token
转换成 userId
参数。
注:此处并没有使用真正的 token
,而是用一个 map
模拟 token
存储, token
为 123
和 456
为有效 token
,分别对应着 userId = 1
和 userId = 2
/** * Token请求包装类,将token字段转换成userId字段 * @author yan * @date 2019年10月17日 */ public class TokenHttpServletWrapper extends HttpServletRequestWrapper{ private Logger logger = LoggerFactory.getLogger(getClass()); private Map<String,Integer> tokenMap; //模拟token public TokenHttpServletWrapper(HttpServletRequest request) { super(request); tokenMap = new HashMap<>() { { put("123", 1); put("456", 2); } }; } @Override public String[] getParameterValues(String name) { //如果请求参数不是userId,则跳过 if(!"userId".equals(name)) { return super.getParameterValues(name); } //检验token,转换成相应的userId String token = super.getParameter("token"); if(token == null) { return null; } logger.debug("token:" + token); Integer userId = tokenMap.get(token); logger.debug("userId:" + userId); return userId == null ? null : new String[] {String.valueOf(userId)}; } } 复制代码
token
参数或者 token
参数是否有效 AbstractFilter
是自定义过滤器抽象类,主要用于添加排除路径功能,其他用法与过滤器一致
public class TokenFilter extends AbstractFilter{ @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { String token = request.getParameter("token"); if(!"123".equals(token) && !"456".equals(token)) { CodeResult codeResult = new CodeResult(CodeEnum.UNAUTHORIZED, null); response.setContentType("text/json;charset=utf-8"); response.getWriter().write(BeanUtil.beanToJson(codeResult)); return; } chain.doFilter(new TokenHttpServletWrapper(request), response); } } 复制代码
@Configuration public class TokenFilterConfig { @Bean public FilterRegistrationBean<Filter> securityFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); Filter filter = new TokenFilter(); registration.setFilter(filter); registration.addUrlPatterns("/*"); registration.setName("tokenFilter"); registration.setOrder(Ordered.HIGHEST_PRECEDENCE); return registration; } } 复制代码
Controller
方法中使用 userId
作为形参 token
参数时或者 token
参数无效时,返回未授权信息 token
参数有效时,获取到相应的 userId