在@PreAuthorize中使用请求标头值



是否可以在@PreAuthorize中使用请求头值?

在我的应用程序中,所有请求都包含一个自定义标头,我需要将其与用户角色结合使用,以确定是否应允许他们访问控制器。

如果有人手动指定一个标头也没关系,因为这不会是一个安全问题,因为最终角色会控制它。但我需要使用它来减少在每个控制器方法中手动检查的次数。

谢谢,马特

1-如果只在少数地方使用,这可能是最快的方法。

@GetMapping(value = "/private-api-method")
@PreAuthorize("#request.getHeader('header-name') == 'localhost:8080'")
public ResponseEntity<String> privateApiMethod(HttpServletRequest request) {
return ResponseEntity.ok("OK!");
}

OR

@GetMapping(value = "/private-api-method")
@PreAuthorize("#header == 'localhost:8080'")
public ResponseEntity<String> privateApiMethod(@RequestHeader("header-name") String header) {
return ResponseEntity.ok("OK!");
}

2-如果你在很多地方使用它,这可能是最好的方法。

(在SecurityService中,您可以添加多种不同的检查方法。(

@GetMapping(value = "/private-api-method")
@PreAuthorize("@securityService.checkHeader(#request)")
public ResponseEntity<String> privateApiMethod(HttpServletRequest request) {
return ResponseEntity.ok("OK!");
}

3-你可以为自己选择一种特殊的方法

一种具有Spring Security 的自定义安全表达式

由于您打算为每个控制器方法检查特定的头/cookie/请求属性,因此您应该选择Filter,因为这将是一个标准,并且您可以通过从OncePerRequestFilter扩展来保证它对每个方法都执行一次

话虽如此,有两种方法可以实现这一点:

  1. 通过扩展AbstractAuthenticationProcessingFilterOncePerRequestFilter

    为此,您可以参考所有人都主张的spring-security-jwt令牌验证流程:

    • 将所需控制器方法的方法安全性添加为@PreAuthorize("hasAuthority('USER_ROLE')")
    • UsernamePasswordAuthenticationFilter之前截获请求,从请求中提取Authentication标头或cookies,并验证声明的令牌值
public class CustomHeaderAuthFilter extends AbstractAuthenticationProcessingFilter{
@Override
public Authentication attemptAuthentication(
HttpServletRequest request, HttpServletResponse response){
// Get all the headers from request, throw exception if your header not found    
Enumeration<String> reqHeaders =  request.getHeaderNames();
Assert.notNull(reqHeaders, "No headers found. Abort operation!");
Collections.list(reqHeaders)
.stream()
.filter(header_ -> header_.equals("TARGET_HEADER_NAME"))
.findAny().ifPresent(header_ -> {
// header found, would go for success-andler
});

// Here it means request has no target header
SecurityContextHolder.clearContext();
failureHandler.onAuthenticationFailure(request, response, new CustomException(""));
}
}

通过这种方式,你需要用WebSecurityConfigurerAdapter注册你的过滤器,如果你从AbstractAuthenticationProcessingFilter扩展,你也可以提供你的AuthenticationProvider

  1. 如dm tr所述,使用@RequestHeader访问rest控制器中的HTTP Headers

也许你可以试试这个

@PreAuthorize("hasAuthority('ROLE_SOMETHING')")
@RequestMapping("PATH")
public void checkIt(@RequestHeader("header-name") String header) {
if (null != header /* && header meets certain condition*/) {
// stuff
} else throw new ResponseStatusException(HttpStatus.FORBIDDEN); // PERMISSION NOT GRANTED, 403 ERROR
}

最新更新