在实际项目中,我们往往会发放一个 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