卓越飞翔博客卓越飞翔博客

卓越飞翔 - 您值得收藏的技术分享站
技术文章11201本站已运行3223

Java源码 Jwt使用Aop方式自定义权限注解认证

使用Aop前置通知方式, 在控制层上使用指定切面注解, 并赋予注解参数为访问接口所需角色权限代码, 进行身份认证和权限校验
Demo环境 JDK11, SpringBoot 2.2.2.RELEASE
相关依赖坐标
implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation 'io.jsonwebtoken:jjwt:0.9.0'

1、自定义权限认证注解

import java.lang.annotation.*;

/**
 * 角色权限校验注解
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface HasRoles {
    String[] roles() default "";
}
2、Aop前置通知切面类

import com.example.dynamicdatatable.domain.SysAccountInfo;
import com.example.dynamicdatatable.enums.AccountType;
import com.example.dynamicdatatable.repository.SysAccountMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashSet;
import java.util.Set;

/**
 * 权限认证切面类
 */
@Aspect
@Slf4j
@Component
public class CheckRoleAop {

    @Pointcut(value = "@annotation(HasRoles)")
    public void pointCut() {};
    @Resource
    private SysAccountMapper accountMapper;
    @Resource
    private HttpServletRequest request;

    /**
     * todo 身份认证和权限比对
     * @param hasRoles  权限认证注解入参
     */
    @Before(value = "pointCut()&&@annotation(hasRoles)")
    public void exec(HasRoles hasRoles) {
        // jwt解密认证
        // ...
        // jwt解密认证结束
        long id = 10; // 模拟解析Token后 取得的id值
        AccountType accountType = AccountType.ADMIN_TYPE;   // 模拟解析Token后, 取得的用户账户类别
        // 每次请求都动态实时的去查询用户信息和权限信息
        SysAccountInfo accountInfo = accountMapper.findById(id, accountType);
        if (ObjectUtils.isEmpty(accountInfo) || !accountInfo.isEnableState() || accountInfo.isDelState()) {
            log.error("用户不存在");
            throw new RuntimeException("用户不存在");
        } else {
            // 模拟从数据库中查询账户拥有的角色身份权限
            Set<String> rolesToken = new HashSet<String>(1) {
                private static final long serialVersionUID = -1307833886578391108L;
                {
                    add("admin");
                }
            };
            String[] roles = hasRoles.roles();
            if (roles.length == 0) {
                return;
            } else {
                for (String role : roles) {
                    if (rolesToken.contains(role)) {
                        // 将解析后的Token信息实体缓存到请求域中
                        JwtSessionCacheEntity jwtSessionCacheEntity = new JwtSessionCacheEntity();
                        jwtSessionCacheEntity.setId(id);
                        jwtSessionCacheEntity.setAccountType(accountType);
                        jwtSessionCacheEntity.setRoleCode("admin");
                        request.setAttribute("info", jwtSessionCacheEntity);
                        return;
                    }
                }
            }
            log.warn("用户无对应的权限");
            throw new RuntimeException("无权限");
        }
    }

}
3、请求域缓存实体类

import lombok.Data;

import java.io.Serializable;

/**
 * Jwt 请求域缓存数据实体
 */
@Data
public class JwtSessionCacheEntity implements Serializable {

    private static final long serialVersionUID = -4634413454684601681L;

    private Long id;
    private String roleCode;
    private AccountType accountType;

}
4、账户类型枚举类

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * 账户类型枚举类
 */
@Getter
@AllArgsConstructor
public enum AccountType {

    ACCOUNT_TYPE(1, "sys_account_info"),
    ADMIN_TYPE(2, "sys_admin_info"),

    ;

    private int code;
    private String tableName;

}
卓越飞翔博客
上一篇: C&C++源码 QT+OPENCV实现监控
下一篇: 模仿某为的运动健康写的echarts
留言与评论(共有 0 条评论)
   
验证码:
隐藏边栏