如何使用 Spring 安全模拟身份验证和授权
How to mock authentication and authorization with Spring Security
我有一个 spring-boot REST API 应用程序。 REST 端点受 spring-security.
保护
这是spring-security的配置:
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.exceptionHandling().authenticationEntryPoint(new CustomForbiddenErrorHandler())
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/api/**").authenticated() // HTTP 403 if the request is not authenticated
.antMatchers("/**").permitAll();
}
它工作正常。如果我在 HTTP header 上没有 auth-token 的情况下进行休息调用,我会返回正确的 HTTP 错误代码。
我可以强制 spring 以某种方式添加一个 self auth-token 如果它没有按顺序显示,这样我就可以在没有自己的访问管理系统的情况下进行 REST 调用吗?稍后安装。
我不是在问如何编写 JUnit 测试。我要问的是如何动态生成模拟 auth-token 并将其添加到请求中(如果它不存在)。
您可以覆盖现有的身份验证过滤器,或创建新的自定义过滤器,以检查请求是否包含不记名令牌。根据结果,您可以按原样处理请求,也可以使用自定义身份验证对象扩充请求。
查看 OAuth2AuthenticationProcessingFilter,这会从传入请求中提取 OAuth2 令牌并使用它来填充 Spring 安全上下文。您可以覆盖它的行为或创建一个新的过滤器,用您的模拟身份验证对象填充安全上下文。
这是一个让您入门的示例代码:
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
boolean debug = logger.isDebugEnabled();
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
try {
Authentication authentication = this.tokenExtractor.extract(request);
if (Objects.isNull(authentication)) {
final UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken("username", "password");
authenticationToken.setDetails(Collections.singletonMap("user_uuid", userUuid.toString()));
final OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(null, authenticationToken);
// You can either ask your authenticatoin manager to authenticate these credentials or directly publish auth success event with your mock auth object.
this.eventPublisher.publishAuthenticationSuccess(oAuth2Authentication);
SecurityContextHolder.getContext().setAuthentication(oAuth2Authentication);
} else {
request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, authentication.getPrincipal());
if (authentication instanceof AbstractAuthenticationToken) {
AbstractAuthenticationToken needsDetails = (AbstractAuthenticationToken)authentication;
needsDetails.setDetails(this.authenticationDetailsSource.buildDetails(request));
}
Authentication authResult = this.authenticationManager.authenticate(authentication);
if (debug) {
logger.debug("Authentication success: " + authResult);
}
this.eventPublisher.publishAuthenticationSuccess(authResult);
SecurityContextHolder.getContext().setAuthentication(authResult);
}
我有一个 spring-boot REST API 应用程序。 REST 端点受 spring-security.
保护这是spring-security的配置:
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.exceptionHandling().authenticationEntryPoint(new CustomForbiddenErrorHandler())
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/api/**").authenticated() // HTTP 403 if the request is not authenticated
.antMatchers("/**").permitAll();
}
它工作正常。如果我在 HTTP header 上没有 auth-token 的情况下进行休息调用,我会返回正确的 HTTP 错误代码。
我可以强制 spring 以某种方式添加一个 self auth-token 如果它没有按顺序显示,这样我就可以在没有自己的访问管理系统的情况下进行 REST 调用吗?稍后安装。
我不是在问如何编写 JUnit 测试。我要问的是如何动态生成模拟 auth-token 并将其添加到请求中(如果它不存在)。
您可以覆盖现有的身份验证过滤器,或创建新的自定义过滤器,以检查请求是否包含不记名令牌。根据结果,您可以按原样处理请求,也可以使用自定义身份验证对象扩充请求。
查看 OAuth2AuthenticationProcessingFilter,这会从传入请求中提取 OAuth2 令牌并使用它来填充 Spring 安全上下文。您可以覆盖它的行为或创建一个新的过滤器,用您的模拟身份验证对象填充安全上下文。
这是一个让您入门的示例代码:
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
boolean debug = logger.isDebugEnabled();
HttpServletRequest request = (HttpServletRequest)req;
HttpServletResponse response = (HttpServletResponse)res;
try {
Authentication authentication = this.tokenExtractor.extract(request);
if (Objects.isNull(authentication)) {
final UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken("username", "password");
authenticationToken.setDetails(Collections.singletonMap("user_uuid", userUuid.toString()));
final OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(null, authenticationToken);
// You can either ask your authenticatoin manager to authenticate these credentials or directly publish auth success event with your mock auth object.
this.eventPublisher.publishAuthenticationSuccess(oAuth2Authentication);
SecurityContextHolder.getContext().setAuthentication(oAuth2Authentication);
} else {
request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, authentication.getPrincipal());
if (authentication instanceof AbstractAuthenticationToken) {
AbstractAuthenticationToken needsDetails = (AbstractAuthenticationToken)authentication;
needsDetails.setDetails(this.authenticationDetailsSource.buildDetails(request));
}
Authentication authResult = this.authenticationManager.authenticate(authentication);
if (debug) {
logger.debug("Authentication success: " + authResult);
}
this.eventPublisher.publishAuthenticationSuccess(authResult);
SecurityContextHolder.getContext().setAuthentication(authResult);
}