前言
有些方法限定只有admin角色的用户访问
加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
一、定义注解
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
//RUNTIME:生命周期:注解不仅被保存到class文件中,还保存在内存中的字节码
public @interface CheckAuthorization {
String value();
}
二、方法上加注解
@PutMapping("/audit/{id}")
@CheckAuthorization("admin")
public Share auditById(@PathVariable Integer id, @RequestBody ShareAuditDTO auditDTO) {
return this.shareService.auditById(id, auditDTO);
}
三、定义切面
import com.itmuch.contentcenter.util.JwtOperator;
import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Objects;
@Aspect //切面注解
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class AuthAspect {
private final JwtOperator jwtOperator;
private void checkToken() {
try {
// 1. 从header里面获取token
HttpServletRequest request = getHttpServletRequest();
String token = request.getHeader("X-Token");
// 2. 校验token是否合法&是否过期;如果不合法或已过期直接抛异常;如果合法放行
Boolean isValid = jwtOperator.validateToken(token);
if (!isValid) {
throw new SecurityException("Token不合法!");
}
// 3. 如果校验成功,那么就将用户的信息设置到request的attribute里面
Claims claims = jwtOperator.getClaimsFromToken(token);
request.setAttribute("id", claims.get("id"));
request.setAttribute("wxNickname", claims.get("wxNickname"));
request.setAttribute("role", claims.get("role"));
} catch (Throwable throwable) {
throw new SecurityException("Token不合法");
}
}
private HttpServletRequest getHttpServletRequest() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
return attributes.getRequest();
}
@Around("@annotation(com.itmuch.contentcenter.auth.CheckAuthorization)")
//加了@CheckAuthorization的方法都会走到这里
public Object checkAuthorization(ProceedingJoinPoint point){
try{
//1.验证token
checkToken();
//2.验证角色是否匹配
HttpServletRequest request = getHttpServletRequest();
//从request中拿role
String role = (String) request.getAttribute("role");
MethodSignature signature = (MethodSignature) point.getSignature();
//拿到了添加了CheckAuthorization注解的方法定义
Method method = signature.getMethod();
CheckAuthorization annotation = method.getAnnotation(CheckAuthorization.class);
String value = annotation.value();
if(!Objects.equals(value,role)){
throw new SecurityException("用户无权访问。");
}
return point.proceed();
}catch (Throwable throwable) {
throw new SecurityException("用户无权访问。");
}
}
}
测试
访问http://localhost:8081/admin/shares/audit/{id}时,
用JWT提前生成token,生成的token的Payload数据role可以为test或admin来测试,并加到hearder里。