【问题标题】:Spring Security with overlapping configurations checks authorization in multiple <http> blocks具有重叠配置的 Spring Security 检查多个 <http> 块中的授权
【发布时间】:2021-12-11 15:22:18
【问题描述】:

我有一个使用 Spring Security 4.2.18 的应用程序,并在 xml 中配置了安全性。现在我正在项目中引入 Spring Boot 2.5.4。升级后,部分请求的安全配置出现问题。

我有一个匹配特定请求的块和一个匹配其余所有请求的块。

<http pattern="/api/**" use-expressions="true" authentication-manager-ref="apiAuthenticationManager" >
    <http-basic/>

    <intercept-url pattern="/api/**" access="hasRole('ROLE_API')"/>
    <csrf disabled="true"/>
</http>


<http pattern="/**" auto-config="true" use-expressions="true" create-session="always" disable-url-rewriting="true"
      authentication-manager-ref="authenticationManager">
    <form-login login-processing-url="/resources/j_spring_security_check" login-page="/login"
                username-parameter="j_username"
                password-parameter="j_password"
                authentication-failure-url="/login?login_error=t" default-target-url="/redirectlogin"/>
    <logout logout-url="/resources/j_spring_security_logout"/>

    ...

    <intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"/>

    ...

</http>

<authentication-manager id="apiAuthenticationManager">
    <authentication-provider user-service-ref="apiUserDetailsService">
    </authentication-provider>
</authentication-manager>

ApiUserDetailsService 遵循规范:

@Service
@Transactional
public class ApiUserDetailsService implements UserDetailsService {

    ...
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
        boolean foundAccount = apiConfig.getUsername().equals(username);
        if (foundAccount) {
            return new User(username, apiConfig.getPassword(), singletonList(new SimpleGrantedAuthority("ROLE_API")));
        }
        throw new UsernameNotFoundException("Could not finder user with name " + username);
    }

}

如果我向/api 下的某些内容发出请求并使用不正确的基本身份验证凭据,我之前会收到 401 Unauthorized 响应。升级后我被重定向到/login 并最终进入重定向循环,因为那里也使用了凭据。

如果我在第二个 &lt;http&gt; 块中删除 &lt;intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"/&gt;,我会得到预期的行为。

如何配置我的应用程序,以便我的请求不会尝试使用第二个 &lt;http&gt; 块中的规则进行授权?我曾尝试使用EntryPoint,但在使用通用&lt;http&gt; 块的方法错误地授权用户之前不会调用它。

【问题讨论】:

  • 通过为 Spring Security logging.level.org.springframework.security=TRACE 启用 TRACE 日志记录可能有助于通过过滤器链跟踪请求。我怀疑请求是由第一个&lt;http&gt; 块处理的,然后重定向原因是进入第二个&lt;http&gt; 块。

标签: spring spring-boot spring-security


【解决方案1】:

您是否尝试过将&lt;intercept-url pattern="/login*" access="permitAll" /&gt; 放在您的&lt;intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"/&gt; 上方,例如:

在第二个 http 块中:

...
<intercept-url pattern="/login*" access="permitAll" />
<intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"/>
...

【讨论】:

  • 问题不是我不能查看 /login 页面,而是我的 api 调用在应该得到 401 响应时被重定向到 /login。
【解决方案2】:

问题不在于配置重叠,而是失败的身份验证被重定向到 /login,而后者又由第二个 &lt;http&gt; 配置处理。

我通过创建AuthenticationEntryPoint 的实现来解决它,该实现在响应中设置401 Unathorized 状态:

@Component
public class BasicAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) {
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
    }
}

然后在我的基本身份验证配置中引用它:

<http pattern="/api/**" use-expressions="true" authentication-manager-ref="apiAuthenticationManager" >
    <http-basic entry-point-ref="basicAuthenticationEntryPoint"/>

    <intercept-url pattern="/api/**" access="hasRole('ROLE_API')"/>
    <csrf disabled="true"/>
</http>

【讨论】:

    猜你喜欢
    • 2019-07-13
    • 1970-01-01
    • 2011-10-29
    • 2021-12-30
    • 1970-01-01
    • 2015-10-09
    • 2019-06-13
    相关资源
    最近更新 更多