[英]spring-boot custom annotation for validating headers
我正在使用spring-boot-1.5.10,並且在我的應用程序中使用spring-security。 我想創建一個自定義批注,並且應該使用securityContextholder ...讓我用示例代碼詳細說明我的問題。
curl -X GET -H“角色:讀取” -H“內容類型:application / json” -H“接受:application / json” -H“應用名稱:sample” -H“應用ID:sample”- H“客戶ID:123” -H“市場:EN” -H“國家/地區代碼:EN” -H“接受語言:application / json” -H“緩存控制:無緩存”“ http:/ / localhost:9992 / api / v1 / apps “
調節器
@GetMapping("/apps")
@PreAuthorize("hasAnyAuthority('ROLE_READ', 'ROLE_WRITE')")
public ResponseEntity<List<Apps>> getApps(@AuthenticationPrincipal AppAuthentication appAuthentication) {
if(appAuthentication.isGrantedAnyOf("ROLE_READ") && isBlank(appAuthentication.getAppContext().customerId())) {
throw new IllegalArgumentException("Missing header customerId");
}
if(appAuthentication.isGrantedAnyOf("ROLE_WRITE") && isBlank(appAuthentication.getAppContext().customerId()) && isBlank(appAuthentication.getAppContext().appId())) {
throw new IllegalArgumentException("Missing header customerId & AppId");
}
//write business logic here
}
spring-security preAuthorize將僅檢查是否允許角色。此外,我可以增強preAuthorize批注,但這對於許多微服務來說是常見的,而且我也沒有接觸安全領域的權限。 因此,我想創建一個自定義注釋。 我們應該配置角色和標題以驗證特定角色。 像下面
@GetMapping("/apps")
@PreAuthorize("hasAnyAuthority('ROLE_READ', 'ROLE_WRITE')")
@ValidateHeaders("role=ROLE_READ",value={"customerId","app-id"})
public ResponseEntity<List<Apps>> getApps(@AuthenticationPrincipal AppAuthentication appAuthentication) {
//write business logic here
}
任何提示都是非常可觀的。
Disclamer-我正在使用Spring Boot 2,因此並非所有內容都適合您
這是我前一段時間實現的簡化版本。 我建議為角色和價值觀實施枚舉。
您無法從@before注釋進行重定向,因此必須拋出異常並使用全局ex處理程序捕獲該異常,然后從那里進行重定向。
還考慮在注釋中添加可選字段-如果有多個角色,則匹配全部或一個,重定向路徑,在沒有訪問權限的情況下調用的異常類型。 然后,您可以在異常處理程序中根據調用的異常進行重定向。 由於您要從gloabl ex處理程序進行重定向,因此,如果添加重定向路徑,則必須將其與拋出的異常捆綁在一起,這意味着您將需要自定義異常。
注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidateHeaders {
Roles[] roles();
String[] values();
}
方面類
@Aspect
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired)) //Autowired annotated lombok generated constructor
public class ValidateHeadersAspect {
private final @NonNull HttpServletRequest request; //Inject request to have header access
private final @NonNull UserService userService;//Your user service here
//Aspect can be placed on clas or method
@Before("within(@com.org.package.ValidateHeaders *) || @annotation(com.org.package.ValidateHeaders)")
public void validateAspect(JoinPoint joinPoint) throws Throwable {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
HasAccess validateHeaders = method.getAnnotation(ValidateHeaders.class);
if(validateHeaders == null) { //If null it was a class level annotation
Class annotatedClass = joinPoint.getSignature().getDeclaringType();
validateHeaders = (ValidateHeaders)annotatedClass.getAnnotation(ValidateHeaders.class);
}
Roles[] roles = validateHeaders.roles(); //Roles listed in annotation
String[] values = validateHeaders.values(); //Values listed in
//Validate request here ... determine isAuthorised
if( !isAuthorized ){
throw new HeaderAuthrizationException()
}
}
}
異常處理程序
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(HeaderAuthrizationException.class)
public RedirectView HeaderAuthrizationException(HeaderAuthrizationException ex) {
return new RedirectView("/redirect");
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.