Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 具有permitAll()和过期身份验证令牌的URL的Spring安全性_Java_Spring_Security_Authentication_Spring Security - Fatal编程技术网

Java 具有permitAll()和过期身份验证令牌的URL的Spring安全性

Java 具有permitAll()和过期身份验证令牌的URL的Spring安全性,java,spring,security,authentication,spring-security,Java,Spring,Security,Authentication,Spring Security,我将Spring4与SpringSecurity、自定义GenericFilterBean和AuthenticationProvider实现一起使用。除了创建新会话的URL之外,我的URL大多是安全的:/v2/session(例如,基于用户名和密码登录,并返回需要验证的后续请求中使用的身份验证令牌),配置如下: @Configuration @ComponentScan(basePackages={"com.api.security"}) @EnableWebSecurity public cl

我将Spring4与SpringSecurity、自定义GenericFilterBean和AuthenticationProvider实现一起使用。除了创建新会话的URL之外,我的URL大多是安全的:/v2/session(例如,基于用户名和密码登录,并返回需要验证的后续请求中使用的身份验证令牌),配置如下:

@Configuration
@ComponentScan(basePackages={"com.api.security"})
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
private ApiAuthenticationProvider apiAuthenticationProvider;

@Autowired
private AuthTokenHeaderAuthenticationFilter authTokenHeaderAuthenticationFilter;

@Autowired
private AuthenticationEntryPoint apiAuthenticationEntryPoint;

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
    auth.authenticationProvider(apiAuthenticationProvider);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .addFilterBefore(authTokenHeaderAuthenticationFilter, BasicAuthenticationFilter.class) // Main auth filter
        .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    http.authorizeRequests()
        .antMatchers(HttpMethod.POST, "/v2/session").permitAll()
        .anyRequest().authenticated();

    http.exceptionHandling()
        .authenticationEntryPoint(apiAuthenticationEntryPoint);
}
}
authTokenHeaderAuthenticationFilter对每个请求运行,并从请求头获取令牌:

/**
 * Main Auth Filter. Always sets Security Context if the Auth token Header is not empty
 */
@Component
public class AuthTokenHeaderAuthenticationFilter extends GenericFilterBean {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    final String token = ((HttpServletRequest) request).getHeader(RequestHeaders.AUTH_TOKEN_HEADER);
    if (StringUtils.isEmpty(token)) {
        chain.doFilter(request, response);
        return;
    }

    try {
            AuthenticationToken authRequest = new AuthenticationToken(token);

              SecurityContextHolder.getContext().setAuthentication(authRequest);
        }
    } catch (AuthenticationException failed) {
        SecurityContextHolder.clearContext();

        return;
    }

    chain.doFilter(request, response); // continue down the chain
}
}

自定义APAuthenticationProvider将尝试根据标头中提供的令牌对所有请求进行身份验证,如果身份验证失败,则抛出AccessException,客户端将收到HTTP 401响应:

@Component
public class ApiAuthenticationProvider implements AuthenticationProvider {

@Autowired
private remoteAuthService remoteAuthService;

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {

    AuthenticationToken authRequest = (AuthenticationToken) authentication;
    String identity = null;

    try {
        identity = remoteAuthService.getUserIdentityFromToken(authRequest.getToken());
    } catch (AccessException e) {
        throw new InvalidAuthTokenException("Cannot get user identity from the token", e);
    }

    return new AuthenticationToken(identity, authRequest.getToken(), getGrantedAuthorites());
    }
    }
这对于需要身份验证的请求来说非常有效。这适用于/v2/session请求,其中没有身份验证头。但是,对于头中(或cookie中-代码示例中未显示;如果客户端未清除头或继续发送cookie和请求,有时可能会发生这种情况)具有过期身份验证令牌的/v2/session请求安全上下文将被初始化,APAuthenticationProvider将抛出异常并用HTTP 401响应客户端

由于/v2/会话已配置为

http.authorizeRequests()
        .antMatchers(HttpMethod.POST, "/v2/session").permitAll()

我希望Spring安全性在调用ApiAuthenticationProvider.authenticate()之前确定这一点。对于配置为permitAll()的URL,筛选器或身份验证提供程序应以何种方式忽略/不引发异常?

在执行请求授权检查之前,会触发Spring安全筛选器。为了使授权检查起作用,假设请求已通过过滤器,并且已设置Spring安全上下文(或未设置,取决于是否传入了身份验证凭据)

在过滤器中,如果令牌不存在,则检查是否继续进行过滤器链处理。不幸的是,如果是,那么它将被传递给您的提供者进行身份验证,这会引发一个异常,因为令牌已过期,因此您将获得401

<>你最好绕过你认为公共的URL的过滤器执行。您可以在过滤器本身或配置类中执行此操作。将以下方法添加到您的
SecurityConfig
类:

@Override
public void configure(WebSecurity webSecurity) {
  webSecurity.ignoring().antMatchers(HttpMethod.POST, "/v2/session");
}

这样做的目的是完全绕过
AuthTokenHeaderAuthenticationFilter
进行
POST/v2/sessions
URL。

检查此线程,它还回答了您的问题:@grigori如何确保我的请求仍然通过安全筛选链的其余部分,例如csrf保护等。然后我需要将该URL保存在permitAll()中。正确的?总之,我将如何配置需要其余spring安全过滤器链服务的公共请求?3年了,仍然不是一个更好的解决方案,这让我有点担心!