JWT令牌如何将令牌token转换为登录者的信息的?

本文介绍了如何利用Spring MVC的HandlerMethodArgumentResolver接口来优化JWT权限认证流程,避免在每个接口中手动解析token。通过创建自定义的TokenArgumentResolver实现类,将用户信息自动注入到Controller方法参数中,从而减少代码重复,提高代码的可读性和维护性。
摘要由CSDN通过智能技术生成

前言

        java项目的权限认证系统大家都熟悉,之前本人也用到过几种认证token的方式,其中JWT是我觉得最神秘的一种,因为我一直没搞明白,在认证完成后,访问业务接口时,接口是怎么把请求头中的token转换为接口中的用户信息的,直到HandlerMethodArgumentResolver这个接口进入我的视野。

一、HandlerMethodArgumentResolver的作用及其中的方法解释:

HandlerMethodArgumentResolver是个接口,这个接口中有两个方法:

public interface HandlerMethodArgumentResolver {
    boolean supportsParameter(MethodParameter parameter);

    @Nullable
    Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception;
}

看方法名应该大致能猜到:

supportsParameter这个方法返回值是boolean,它的作用是判断Controller层中的参数,是否满足条件,满足条件则执行resolveArgument方法,不满足则跳过。

resolveArgument方法,它只有在supportsParameter方法返回true的情况下才会被调用。用于处理一些业务,将返回值赋值给Controller层中的这个参数。

我们可以将HandlerMethodArgumentResolver理解为是一个参数解析器,我们可以通过写一个类实现HandlerMethodArgumentResolver接口来实现对Controller层中方法参数的修改。

二、项目实现

1、比如,我们现在用JWT方式登陆后需要通过下面的接口获取当前登录人的信息和权限菜单等详细信息。

@GetMapping("/routes")
@ApiOperationSupport(order = 7)
@ApiOperation(value = "前端菜单数据", notes = "前端菜单数据")
public R<List<MenuVO>> routes(HttpServletRequest request) {
    Claims claims = getClaims(request);
    if (claims == null) {
        return null;
    } else {
        Long userId = claims.get("user_id");
        String roleId = claims.get("role_id");
        String deptId = claims.get("dept_id");
        String account = claims.get("account");
        String roleName = claims.get("role_name");
        String userName = claims.get("user_name");
        User user = new User();
        user.setUserId(userId);
        user.setTenantId(tenantId);
        user.setAccount(account);
        user.setRoleId(roleId);
        user.setDeptId(deptId);
        user.setRoleName(roleName);
        user.setUserName(userName);
    }
	List<MenuVO> list = menuService.routes((user == null || user.getUserId() == 0L) ? null : user.getRoleId());
	return R.data(list);
}

但是,在项目中肯定每个接口需要这样获取参数,这样的话代码太臃肿了。我们可以稍微改造一下,用HandlerMethodArgumentResolver这个接口:

2、首先写个实现类实现这个接口中的方法:

public class TokenArgumentResolver implements HandlerMethodArgumentResolver {
    private static final Logger log = LoggerFactory.getLogger(TokenArgumentResolver.class);

    public TokenArgumentResolver() {
    }

    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.getParameterType().equals(User.class);
    }

    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) {
        return SecureUtil.getUser();
    }
}

然后将这个实现类添加到项目的拦截其中:

@Configuration(
    proxyBeanMethods = false
)
@EnableCaching
@Order(-2147483648)
public class MyWebMvcConfiguration implements WebMvcConfigurer {
    private static final Logger log = LoggerFactory.getLogger(BladeWebMvcConfiguration.class);

    public MyWebMvcConfiguration() {
    }

    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new TokenArgumentResolver());
    }
}

这样在项目接口请求时会进入到我们自定义的TokenArgumentResolver类中进行解析接口类和参数信息。

然后,我们的接口就可以这样写啦:

@GetMapping("/routes")
@ApiOperationSupport(order = 7)
@ApiOperation(value = "前端菜单数据", notes = "前端菜单数据")
public R<List<MenuVO>> routes(User user) {
	List<MenuVO> list = menuService.routes((user == null || user.getUserId() == 0L) ? null : user.getRoleId());
	return R.data(list);
}

这样就不用每个接口都解析请求头中的token了,可以拿到token对应的用户信息

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值