东哈俄伊朝族永赢 發表於 2023-12-6 10:37:59

springboot如何完美通过token获取用户信息

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>1. 什么是Token?</li><li>2. 如何优雅的获取用户信息?</li><ul class="second_class_ul"><li>1.1. 创建CurrentUserUuid接口</li><li>1.2. 创建oginUserHandlerMethodArgumentResolver解析器</li></ul><li>3. 总结</li><ul class="second_class_ul"></ul></ul></div><p class="maodian"></p><h2>1. 什么是Token?</h2>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202312/2023120610342674.png" /></p>
<blockquote><p>身份验证令牌(Authentication Token):在身份验证过程中,&ldquo;token&rdquo;<br />可以表示一个包含用户身份信息的令牌。</p></blockquote>
<p>例如</p>
<p><code>Token(JWT)</code>是一种常见的身份验证令牌,它包含用户的身份信息(例如用户名或用户ID)以及其他相关信息,如权限或过期时间。无意义令牌token,这种一般在获取后通过<code>nosql</code>查询token对应的用户信息。</p>
<p>当然,设计token网上大多有现成的解决方案,但是通过token如何拿个人信息呢?</p>
<p class="maodian"></p><h2>2. 如何优雅的获取用户信息?</h2>
<p>虽然token是用户凭证,但是在后端中,token是不能直接和数据进行交互的,我们需要转换成token用户信息。</p>
<p>解决思路:</p>
<p>我们大多会在过滤器filter进行token检验,在这里我们已经已经从header中解析并且验证了token了。如果我们要是再在Controller中获取header,在解决,感觉一点也不优雅。</p>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202312/2023120610342675.png" /></p>
<p><strong>我们的两种解决方案</strong>:</p>
<p>通过header进行解析(<strong>推荐</strong>):</p>
<blockquote><p>哈哈哈,没想到我们还是从这种low的方法里弄的吧。 实际上nosql性能很不错,再查一次也无伤大雅,并且这种方式耦合度较低,符合代码规范。</p></blockquote>
<p>我们可以通过注解的方式,可以尽量美观很多</p>
<p class="maodian"></p><h3>1.1. 创建CurrentUserUuid接口</h3>
<div class="jb51code"><pre class="brush:java;">@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface CurrentUserUuid {
}
</pre></div>
<p class="maodian"></p><h3>1.2. 创建oginUserHandlerMethodArgumentResolver解析器</h3>
<p style="text-align:center"><img alt="" src="https://img.jbzj.com/file_images/article/202312/2023120610342676.png" /></p>
<div class="jb51code"><pre class="brush:java;">@Component
public class LoginUserHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {
    @Resource
    private TokenUtil tokenUtil;

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
      return parameter.hasParameterAnnotation(CurrentUserUuid.class) &amp;&amp;
                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);
    }
}
</pre></div>
<p>过滤器二次封装请求体</p>
<blockquote><p>我们可以在第一次过滤器查的时候,把对应的信息封装到请求中,但是请求多变,get,post参数一般在不同的位置上,需要写更复杂的结构</p></blockquote>
<div class="jb51code"><pre class="brush:java;">@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 Enumeration&lt;String&gt; getParameterNames() {       
                Set&lt;String&gt; paramNames = new LinkedHashSet&lt;&gt;();       
                paramNames.add("loginUserId");       
                Enumeration&lt;String&gt; names =super.getParameterNames();       
                while(names.hasMoreElements()) {       
                  paramNames.add(names.nextElement());       
                }       
                return Collections.enumeration(paramNames);       
            }       
    };       
    chain.doFilter(requestWrapper, httpResponse);       
}
</pre></div>
<p><strong>这种好处是只需要查一次,但是请求参数多变,需要写很多额外的解构去处理,并且增加了耦合度</strong></p>
<p class="maodian"></p><h2>3. 总结</h2>
<p>我还是推荐方法1,无疑,虽然多查一次,但是结构简单,耦合度低,并且代码较为简洁。</p>
<p></p>
<p>到此这篇关于springboot如何完美通过token获取用户信息的文章就介绍到这了,更多相关springboot token获取用户信息内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>SpringBoot中获取微信用户信息的方法</li><li>SpringBoot+SpringCloud用户信息微服务传递实现解析</li><li>Springboot+Shiro记录用户登录信息并获取当前登录用户信息的实现代码</li><li>SpringBoot使用Redis的zset统计在线用户信息</li><li>Springboot通过请求头获取当前用户信息方法详细示范</li><li>SpringBoot登录、退出、获取用户信息的session处理方案</li><li>springboot登录拦截器+ThreadLocal实现用户信息存储的实例代码</li><li>SpringBoot通过参数注解自动获取当前用户信息的方法</li><li>SpringBoot中的ThreadLocal保存请求用户信息的实例demo</li><li>springboot获取当前用户信息的三种方式</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: springboot如何完美通过token获取用户信息