跟我学Springboot开发后端管理系统8:Matrxi-Web权限设计实现

2020/05/08

上篇文章讲述了Matrix-web整体实现的权限控制的思路。现在来回顾一下:

  • 首先,用户需要登录,填用户名、密码,后端接收到登录请求,进行用户、密码的校验,校验成功后则根据用户名生成Token,并返回给浏览器。
  • 浏览器收到Token后,会存储在本地的LocalStorge里。
  • 后续浏览器发起请求时都携带该Token,请求达到后端后,会在Filter进行判断,首选判断是否为白名单url(比如登录接口url),如果是则放行;否则进入Token验证。如果有Token且解析成功,则放行,否则,返回无权限访问。
  • Filter判断后,请求达到具体的Controller层,如果在Controller层上加上了权限判断的注解,则生成代理类。代理类在执行具体方法前会根据Token判断权限。
    • 取出用户的Token并解析得到该请求的userId,根据userId在从存储层获取用户的权限点。权限控制是RBAC这种方式实现的。
  • 获取到用户权限点后,获取权限判断的注解的权限信息,看用户权限点是否包含权限注解的权限信息,如果包含,则权限校验通过,否则则请求返回无权限。

本篇文章主要讲述在Matrix-Web中是如何实现的,主要讲解一些代码细节

用户登录成功,生成Token

用户登录接口是没有做权限控制的,是任何人都可以访问。请求需要携带用户名、密码,后端服务校验用户名、密码正确后,生成Token。登陆接口如下:

    @PostMapping("/login")
    public RespDTO login(@RequestParam String username, @RequestParam String password) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", username);
        SysUser user = sysUserService.getOne(queryWrapper);
        if (user == null) {
            //异步存储登陆日志
            saveSysLoginLog(username, null, false);
            throw new AriesException(USER_NOT_EXIST);
        }
        if (!user.getPassword().equals(MD5Utils.encrypt(password))) {
            saveSysLoginLog(username, null, false);
            throw new AriesException(PWD_ERROR);
        }
        //登录成功
        String jwt;
        Map<String, String> result = new HashMap<>(1);
        try {
            jwt = JWTUtils.createJWT(user.getId() + "", user.getUserId(), 599999999L);
            result.put("token", jwt);
            log.info("login success,{}", jwt);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //异步存储登陆日志
        saveSysLoginLog(username, user.getRealname(), true);
        return RespDTO.onSuc(result);
    }

在Matrix-web中生成Jwt的是采用开源的jjwt,在工程的pom文件引入以下的依赖:

<dependency>
  <groupId>io.jsonwebtoken</groupId>      <artifactId>jjwt</artifactId>
 <version>${jjwt.version}</version>
</dependency>

Matrix-Web项目中封装好了JWTUtils用于生成和解析JWT,具体生成步骤和解析步骤,请查看每一步的代码注释,在这里就不再重复。


public class JWTUtils {

//生成Token
public static String createJWT(String id, String subject, long ttlMillis) throws Exception {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; //指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        Map<String,Object>