基于自定义注解手写权限控制
2020-03-28 01:52:24 1148
方法一: AOP 方法二: 拦截器
项目结构
项目依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
配置
spring:
aop:
proxy-target-class: true
定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Role {
/**
* 角色名 默认值:游客
* @return
*/
String value() default "NORMAL";
}
控制层
package com.github.controller;
import com.github.annotations.Role;
import com.github.entity.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpSession;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private HttpSession session;
/**
* 登录
*
* @param username
* @param password
*/
@Role
@PostMapping("/login")
public Result login(String username, String password) {
if ("admin".equals(username)) {
session.setAttribute(username, "ADMIN");
} else {
session.setAttribute(username, "USER");
}
return Result.resultFactory("登录成功", 200);
}
@Role("USER")
@GetMapping("/user")
public Result user() {
return Result.resultFactory("访问成功", 200, "USER权限");
}
@Role("ADMIN")
@GetMapping("/admin")
public Result admin() {
return Result.resultFactory("访问成功", 200, "ADMIN权限");
}
}
响应信息类
package com.github.entity;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.util.Date;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Result {
private Date timestamp;
private Integer status;
private String error;
private String message;
private String path;
private Object data;
private Result() {
}
@Override
public String toString() {
return "Result{" +
"timestamp=" + timestamp +
", status=" + status +
", error='" + error + '\'' +
", message='" + message + '\'' +
", path='" + path + '\'' +
", data=" + data +
'}';
}
getter&setter...
public static Result resultFactory(String message, Integer status, Object data) {
Result result = new Result();
result.setTimestamp(new Date());
result.setMessage(message);
result.setStatus(status);
result.setData(data);
return result;
}
public static Result resultFactory(String message, Integer status) {
Result result = new Result();
result.setTimestamp(new Date());
result.setMessage(message);
result.setStatus(status);
return result;
}
}
切面类
package com.github.aop;
import com.github.annotations.Role;
import com.github.controller.UserController;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
@Aspect
@Component
public class UserAspect {
@Autowired
private HttpSession session;
@Autowired
private HttpServletRequest request;
@Pointcut("execution(public * com.github.controller.*.*(..))")
public void LogAspect() {
System.out.println("切入点");
}
@Before("LogAspect()")
public void doBefore(JoinPoint joinPoint) {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature)signature;
Method targetMethod = methodSignature.getMethod();
Role roleAnnotation = targetMethod.getAnnotation(Role.class);
String nameKey = request.getHeader("name");
String role = (String)session.getAttribute(nameKey);
if (roleAnnotation.value().equals("NORMAL")) {
System.out.println("游客访问");
} else if (roleAnnotation.value().equals(role)) {
System.out.println("权限校验通过");
} else {
throw new RuntimeException("权限不足");
}
}
}
启动测试
- 登录
- 访问user接口
- 访问admin接口
- 用admin登录后再次访问admin接口
项目链接 提取码:hi7m
但要注意此项目定义的aop发生在SpringMVC的参数注入
之后, 即前端传入的json参数被转为java对象后, 才会执行aop内的逻辑, 在一些场景下并不适用
方法二:
使用org.springframework.web.servlet.HandlerInterceptor
这个接口
实现这个方法
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception
其中handler参数可以强转为org.springframework.web.method.HandlerMethod
, 该对象提供这个方法
Role role = ((HandlerMethod) handler).getMethodAnnotation(Role.class);
也能实现权限判断