token 值处理及鉴权源代码介绍

登录功能代码主要用于验证登录信息并生成 token 值,当然这只是第一步——生成身份验证信息,接下来笔者介绍登录模块中的用户身份保持和身份验证。用户身份保持和身份验证这两个概念并不复杂,结合前文中的登录流程理解即可。前文中处理的流程分支是 token 值不存在,进入登录页面。那么,如果 token 值存在,即已经登录成功,又该怎样进行身份验证?登录成功后会获得一个 token 值,该怎样使用这个 token 值?本节就来讲解这些知识。

后端处理 token 值的步骤总结如下。

  1. 生成 token 值,这在 3.2 节已经介绍过。

  2. 获取请求中的 token 值。

  3. 验证 token 值,查看是否存在、是否过期等。

实现登录功能后,需要对用户的登录状态进行验证,这里所说的登录状态即 “token 值是否存在及 token 值是否有效”,而 token 值是否有效,则通过后端代码验证。由于大部分接口都需要进行登录验证,如果每个方法都添加查询用户数据的语句,则有些多余,因此对方法做了抽取,通过注解切面的形式返回用户信息。

对于管理员用户的身份鉴权,在功能实现时定义了一个 @TokenToAdminUser 注解。之后自定义了一个方法参数解析器,在需要用户身份信息的方法定义上添加 @TokenToAdminUser 注解,通过方法参数解析器来获得当前登录的对象信息,自定义的 TokenToAdminUserMethodArgumentResolver 代码如下:

package ltd.user.cloud.newbee.config.handler;

import ltd.user.cloud.newbee.annotation.TokenToAdminUser;
import ltd.user.cloud.newbee.dao.NewBeeAdminUserTokenMapper;
import ltd.user.cloud.newbee.entity.AdminUserToken;
import ltd.common.cloud.newbee.exception.NewBeeMallException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

@Component
public class TokenToAdminUserMethodArgumentResolver implements HandlerMethodArgumentResolver {

    @Autowired
    private NewBeeAdminUserTokenMapper newBeeAdminUserTokenMapper;

    public TokenToAdminUserMethodArgumentResolver() {
    }

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        if (parameter.hasParameterAnnotation(TokenToAdminUser.class)) {
            return true;
        }
        return false;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter,
                                  ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest,

                                  WebDataBinderFactory binderFactory) {
        if (parameter.getParameterAnnotation(TokenToAdminUser.class) instanceof TokenToAdminUser) {
            String token = webRequest.getHeader("token");
            if (null != token && !"".equals(token) && token.length() == 32) {
                AdminUserToken adminUserToken = newBeeAdminUserTokenMapper.selectByToken(token);
                if (adminUserToken == null) {
                    NewBeeMallException.fail("ADMIN_NOT_LOGIN_ERROR");
                } else if (adminUserToken.getExpireTime().getTime() <= System.currentTimeMillis()) {
                    NewBeeMallException.fail("ADMIN_TOKEN_EXPIRE_ERROR");
                }
                return adminUserToken;
            } else {
                NewBeeMallException.fail("ADMIN_NOT_LOGIN_ERROR");
            }
        }
        return null;
    }
}

源代码在 newbee-mall-cloud-user-web 模块下的 ltd.user.cloud.newbee.service.config.handler.TokenToAdminUserMethodArgumentResolver 类中。

执行逻辑如下。

  1. 获取请求头中的 token 值,若不存在,则返回错误信息给前端;若存在,则继续后续流程。

  2. 通过 token 值来查询 AdminUserToken 对象,查看是否存在或是否过期,若不存在或已过期,则返回错误信息给前端;若正常,则继续后续流程。

  3. WebMvcConfigurer 中配置 TokenToAdminUserMethodArgumentResolver,使其生效,代码如下:

@Configuration
public class AdminUserWebMvcConfigurer extends WebMvcConfigurationSupport {

    @Autowired
    private TokenToAdminUserMethodArgumentResolver tokenToAdminUserMethodArgumentResolver;

    /**
     * @param argumentResolvers
     * @tip @TokenToAdminUser 注解处理方法
     */
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(tokenToAdminUserMethodArgumentResolver);
    }
}

源代码在 newbee-mall-cloud-user-web 模块下的 ltd.user.cloud.newbee.config.AdminUserWebMvcConfigurer 类中。

如此,在需要进行用户鉴权的 API 定义上添加 @TokenToAdminUser 注解,之后进行相应的代码逻辑处理。在本实战项目中,有两种用户身份,分别是 管理员用户商城用户,两种身份的登录功能及鉴权功能的实现方式基本一致,后续就不再占用篇幅单独介绍商城用户的登录功能和鉴权功能了。