自定义拦截器进行权限验证
涉及到的姿势:
- 自定义注解
- 拦截器
- Spring Boot添加拦截器
文章目录:
自定义注解
@Target(ElementType.METHOD)//作用在方法
@Retention(RetentionPolicy.RUNTIME)//仅在运行时
@Documented
public @interface RoleAnnotation {
/**
* <b>“且”关系的Role</b>
* <p>必须指定type</p>
*/
public static String TYPE_AND = "and";
/**
* <b>“或”关系的Role</b>
*/
public static String TYPE_OR = "or";
/**
* <b>“混合”关系的Role</b>
* <p>必须指定type</p>
*/
public static String TYPE_MIXED
= "mixed";
/**
* <b>Role之间的关联方式</b>
*/
String type() default
RoleAnnotation.TYPE_OR;
/**
* <b>“且”关系的Role</b>
* <p>必须指定type</p>
*/
String[] and() default {};
/**
* <b>“或”关系的Role</b>
*/
@AliasFor("value")
String[] or() default {};
@AliasFor("or")
String[] value() default {};
/**
* <b>“混合”关系的Role</b>
* <p>必须指定type</p>
*/
String mixed() default "";
// ( (hr && fe) || admin )
}
在这里定义的是自定义注解,只相当于接口,还没有实现。
在下面的拦截器中,会出现自定义注解的实现。
在这里提两个姿势点:
- @AliasFor(“or”)是取别名,这样就可以让使用注解人,使用自己喜欢的注解关键字。
- value()方法是注解的默认方法,给value赋值的时候,@RoleAnnotation(value = “”) 可以直接写成@RoleAnnotation( “”)。再加上@AliasFor的作用,你就可以让自定义注解,将缺省值赋值给你想要的那个字段。
自定义拦截器
@Service("qiYunRoleInterceptor")
public class RoleInterceptor implements HandlerInterceptor {
@Autowired
private TokenStore tokenStore;
@Override
public boolean preHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler)
throws Exception {
HandlerMethod handlerMethod =(HandlerMethod) handler;
RoleAnnotation roleAnnotation =
handlerMethod.getMethodAnnotation(RoleAnnotation.class);// 在这里使用了自定义注解,也就相当于注解的实现类
if (roleAnnotation == null) {
return true;
}
String token = request.getParameter("access_token");
if (StringUtils.isEmpty(token)) {
noPermission(response);
return false;
}
OAuth2Authentication auth = tokenStore.readAuthentication(token);
Collection<GrantedAuthority> authorities = auth.getAuthorities();
if (authorities.isEmpty()) {
noPermission(response);
return false;
}
Set<String> permissons = new HashSet<String>();
for (GrantedAuthority authority : authorities) {
permissons.add(authority.getAuthority());
}
boolean hasRole = false;
String dealType = roleAnnotation.type();
switch (dealType) {
case RoleAnnotation.TYPE_OR :
String[] orRoles = roleAnnotation.or();
for (String orRole : orRoles) {
if (permissons.contains(orRole)) {
hasRole = true;
break;
}
};
break;
case RoleAnnotation.TYPE_AND :
String[] andRoles = roleAnnotation.and();
Set<String> requireRoles = new HashSet<String>();
for (String role : andRoles) {
requireRoles.add(role);
}
if (permissons.containsAll(requireRoles)) {
hasRole = true;
}
break;
case RoleAnnotation.TYPE_MIXED :
break;
}
if (!hasRole) {
noPermission(response);
}
return hasRole;
}
private void noPermission(HttpServletResponse response) throws IOException {
response.setContentType("application/json; charset=utf-8");
response.setCharacterEncoding("UTF-8");
JSONObject json = new JSONObject();
json.put("error code", "500");
json.put("description", "no permission");
String error = json.toString();
OutputStream out = response.getOutputStream();
out.write(error.getBytes("UTF-8"));
out.flush();
out.close();
}
}
配置WebMvcConfigurer
@Configuration
public class MvcConfigurer implements WebMvcConfigurer {
@Autowired
@Qualifier("qiYunRoleInterceptor")
private HandlerInterceptor interceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptor).addPathPatterns("/api/**");
}
}