本帖最后由 aBin9999 于 2023-4-20 19:52 编辑
使用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;
}
|