我们知道权限控制是不能交给前端去做的,因为一但后端的接口所暴露,是十分危险的一件事,所以前端发起的请求的安全性无从考证,最终的权限控制还是要交给后端去判断。
Shiro和SpringSecurity是都具备权限控制的两个框架,但是如果自己的小项目在权限控制方面要求比较简单,那么这两个框架就显得有些“重”,而且SpringSecurity配置起来还比较麻烦。
本文所实现的权限控制是按等级划分的,即所有用户(游客、普通用户、管理员、超级管理员等)都有一个type字段来标识其身份:
例如-1指游客、0是普通用户、1是VIP、2是管理员、3是超级管理员等以此类推。这个字段即充当其“角色”,又充当其“权限(等级)”。其中低等级用户不能请求高等级的接口,高等级用户向下兼容,可以访问低等级的接口。
详细代码如下,首先是:
1. 权限枚举类
我们首先要把权限枚举类定义出来:
public enum AccessLevel {
ALL(-1, "all"),
LOGIN(0, "login"),
VIP(1, "vip"),
ADMIN(2, "admin"),
SUPER(3, "super");
int code;
String msg;
AccessLevel(int code, String msg) {
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
2. 自定义权限控制注解
其次是用在每个接口方法上的权限控制注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented // 在生成javac时显示该注解的信息
@Inherited
public @interface Access {
AccessLevel level() default AccessLevel.ALL; //默认为ALL
}
3. 自定义权限拦截器
其次是自定义权限拦截器Interceptor:
@Component
public class AccessInterceptor extends HandlerInterceptorAdapter {
private Logger logger = LoggerFactory.getLogger(AccessInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if (!(handler instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
Access access = method.getAnnotation(Access.class);
if (access == null) {
// 如果注解为null, 说明不需要拦截, 直接放过
return true;
}
// 如果是所有都能访问权限直接放行
if (access.level() == AccessLevel.ALL) {
return true;
}
if (access.level().getCode() >= AccessLevel.LOGIN.getCode()) {
//这里为自己写的获取登录用户的信息的方法,大家可以根据自己的方法修改
User user = UserUtils.getLoginUser();
if (user == null || user.getId() == null) {
response.setStatus(401);
logger.info("access " + method.getName() + " Not logged in");
return false;
}
if (user.getType() < access.level().getCode()) {
response.setStatus(403);
logger.info("access " + method.getName() + " No authority");
return false;
}
}
return true;
}
4. 使用自定义权限拦截器
我们需要使该拦截器生效:
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AccessInterceptor());
}
}
5. 使用
我们需要在方法上使用该注解:
@GetMapping("/test")
@Access(level = AccessLevel.VIP)
public AjaxResponse test(){
AjaxResponse.setData("测试成功!");
return AjaxResponse.newSuccess();
}
这样我们就可以自己来实现最简单权限控制,大家还可以灵活去更改权限和拦截器。