SpringBoot(六)基于token快速获取用户登录信息

学习内容

通过实现HandlerMethodArgumentResolver接口,快速获取基于token登录的用户信息。这里简单介绍一下我一般是如何基于token来登录的。

  1. 用户登录成功后,通过一些算法(例如:雪花算法)生成一个唯一的字符串token,然后使用Redis存储用户的信息,以token为key,用户的登录信息为value,并将token传给客户端或者直接将token存储在cookie里面。
  2. 当用户请求需要登录的页面时,获取token,然后拿着该token去Redis中获取用户信息。
  3. 如果不存在该token,则说明当前用户未登录,直接抛出异常。

编写代码

  1. 新建LoginUser实体类,用于存储登录用户信息。
public class LoginUser {
    private Long id;
    private String username;
    // 省略get、set方法
}
  1. 新建LoginUserArgumentResolver类,用于获取用户信息
@Component
public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        Class<?> clazz = parameter.getParameterType();
        return clazz==LoginUser.class;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
        String token = request.getParameter("token");
        // 然后根据token获取用户登录信息,这里省略获取用户信息的过程,随便填写一些数据
        LoginUser loginUser = new LoginUser();
        loginUser.setId(1L);
        loginUser.setUsername("lizhencheng");
        return loginUser;
    }
}
  1. 新建一个配置类
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private LoginUserArgumentResolver loginUserArgumentResolver;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(loginUserArgumentResolver);
    }
}
  1. 编写一个Controller查看效果
@RestController
public class IndexController {

    @GetMapping("/getLoginUserInfo")
    public Object getLoginUserInfo(LoginUser loginUser) {
        return loginUser;
    }
}

在浏览器输入获取用户信息的地址
https://i-blog.csdnimg.cn/blog_migrate/e3b6236bee86dbcf655c40503bf35a60.png

可以看到,我们只需要将LoginUser以参数的方式注入到每个方法中就可以获取到用户的信息。

改造代码

前面我们把获取用户信息的代码放在了LoginUserArgumentResolver中,而我们获取用户信息的时候还需要做一些权限的认证,一般使用过滤器或者拦截器来做权限校验,我这里就使用拦截器来处理了。

  1. 新建UserContext类,存放登录的用户信息
public class UserContext {
    private static ThreadLocal<LoginUser> userHolder = new ThreadLocal<LoginUser>();
    
    public static void setUser(LoginUser loginUser) {
        userHolder.set(loginUser);
    }
    
    public static LoginUser getUser() {
        return userHolder.get();
    }
}
  1. 新建拦截器LoginInterceptor
@Service
public class LoginInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            LoginUser loginUser = getUser(request, response);
            UserContext.setUser(loginUser);
        }
        return super.preHandle(request, response, handler);
    }

    private LoginUser getUser(HttpServletRequest request, HttpServletResponse response) {
        String token = request.getParameter("token");
        // 然后根据token获取用户登录信息,这里省略获取用户信息的过程
        LoginUser loginUser = new LoginUser();
        loginUser.setId(1L);
        loginUser.setUsername("lizhencheng");

        // 如果这里校验用户信息失败,则直接抛出异常

        return loginUser;
    }
}
  1. 修改LoginUserArgumentResolver中的代码
@Component
public class LoginUserArgumentResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        Class<?> clazz = parameter.getParameterType();
        return clazz==LoginUser.class;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        return UserContext.getUser();
    }
}
  1. 修改WebConfig,注入拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;

    @Autowired
    private LoginUserArgumentResolver loginUserArgumentResolver;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(loginUserArgumentResolver);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**"); //配置拦截规则
    }
}

到这里代码就修改完成了,一般我们会在拦截器中校验用户的登录信息,如果校验失败,则抛出异常。

代码地址:https://github.com/923226145/SpringBoot-learning/tree/master/springboot-chapter6

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值