身份验证令牌(Authentication Token):在身份验证过程中,“token”
可以表示一个包含用户身份信息的令牌。
例如
当然,设计token网上大多有现成的解决方案,但是通过token如何拿个人信息呢?
虽然token是用户凭证,但是在后端中,token是不能直接和数据进行交互的,我们需要转换成token用户信息。
解决思路:
我们大多会在过滤器filter进行token检验,在这里我们已经已经从header中解析并且验证了token了。如果我们要是再在Controller中获取header,在解决,感觉一点也不优雅。
我们的两种解决方案:
哈哈哈,没想到我们还是从这种low的方法里弄的吧。 实际上nosql性能很不错,再查一次也无伤大雅,并且这种方式耦合度较低,符合代码规范。
我们可以通过注解的方式,可以尽量美观很多
1.1. 创建CurrentUserUuid接口
@Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) public @interface CurrentUserUuid { }
1.2. 创建oginUserHandlerMethodArgumentResolver解析器
@Component public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver { @Resource private TokenUtil tokenUtil; @Override public boolean supportsParameter(MethodParameter parameter) { return parameter.hasParameterAnnotation(CurrentUserUuid.class) && parameter.getParameterType().isAssignableFrom(String.class); } @Override public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container, NativeWebRequest request, WebDataBinderFactory factory) { // header中获取用户token String token = request.getHeader("Authorization"); // TODO 根据userId获取User信息,这里省略,直接创建一个User对象。 return tokenUtil.getUserToken(token); } }
我们可以在第一次过滤器查的时候,把对应的信息封装到请求中,但是请求多变,get,post参数一般在不同的位置上,需要写更复杂的结构
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; String token = request.getHeader("token"); JWTResult result = JWTUtils.checkToken(token); Long userId = result.getUserId(); HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(httpRequest) { @Override public String[] getParameterValues(String name) { if (name.equals("loginUserId")) { return new String[] { userId .toString() }; } return super.getParameterValues(name); } @Override public EnumerationgetParameterNames() { Set paramNames = new LinkedHashSet<>(); paramNames.add("loginUserId"); Enumeration names = super.getParameterNames(); while(names.hasMoreElements()) { paramNames.add(names.nextElement()); } return Collections.enumeration(paramNames); } }; chain.doFilter(requestWrapper, httpResponse); }
这种好处是只需要查一次,但是请求参数多变,需要写很多额外的解构去处理,并且增加了耦合度
我还是推荐方法1,无疑,虽然多查一次,但是结构简单,耦合度低,并且代码较为简洁。