Spring Boot實現OAuth 2.0(二)-- 自定義許可權驗證
阿新 • • 發佈:2019-02-04
自定義攔截器進行許可權驗證
涉及到的姿勢:
- 自定義註解
- 攔截器
- 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/**");
}
}