微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么AccessDeniedException和AuthenticationException的处理方式不同

如何解决为什么AccessDeniedException和AuthenticationException的处理方式不同

我使用Spring Boot 2和Spring Security 5创建了一个演示应用程序。源位于here

它提供了两种端点-HTML网页和REST API。因此,WebSecurityConfigurerAdapter的两个子类被引入如下:

@Configuration
@Order(1)
public class ApiSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.antMatcher("/api/**")
            .authorizeRequests()
            .antMatchers("/api/admin**").hasRole("ADMIN")
            .anyRequest().authenticated()
            .and().httpBasic();
    }
}

@Configuration
public class PageSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**")
            .authorizeRequests()
            .antMatchers("/login").permitAll()
            .anyRequest().authenticated()
            .and().formLogin().loginPage("/login").permitAll().defaultSuccessUrl("/index")
            .and().logout()
            .invalidateHttpSession(true).deleteCookies("JSESSIONID")
            .logoutSuccessUrl("/login").permitAll();
    }
}

在以下三种情况下,REST api调用将导致身份验证和授权失败:

  1. 未提供受保护端点的凭据
  2. 提供的凭据错误
  3. 正确的凭据提供了错误的角色

结果显示,在情况1和3中org.springframework.security.access.AccessDeniedException上升,在情况2中org.springframework.security.authentication.BadCredentialsException上升,三种情况的返回值为:

  1. HTTP状态为401的json错误消息
  2. HTTP状态302重定向到/ login端点返回
  3. HTTP状态为403的json错误消息

对于情况2,该现象已在另一本question中进行了解释。通常,这是因为异常将由错误端点/error处理,并且在Spring Boot 2中该端点也已受到保护,因此需要登录(详细信息Spring security 5 "Bad credentials" exception not shown with errorDetails)。

进一步的问题是,为什么案例1和案例3没有采用相同的机制处理?错误处理程序为什么不使用AccessDeniedException端点处理/error

解决方法

HTTP.401或»未经身份验证«是因为安全上下文未收到任何凭据。而且,它还取决于所调用的URL(静态页面,角色等)。通常,浏览器会显示一个登录对话框。您的插图不包含此转发案例到登录表单的任何配置。

HTTP.403或»Forbidden«已在链的末端:错误的角色,因此无权访问(无转发,无浏览器对话框)。

您的* SecurityConfig是否驻留在不同的组件/ JAR中?我不这么认为,因为您使用了@Order注释。如果您打算同时激活两个对象,并且它们位于同一JAR中,则将它们合并为一个。这样一来,在不牢记一个或多个另一个的情况下,它的确切含义就更加明显。

我也只能猜测您的角色是如何表达的。至少存在三个不同的选项,例如@RolesAllowed,Spring EL或与您一样。请注意Spring的授予权限和角色之间的区别。如果未进行配置,则后者必须以'ROLE_'开头,否则无法通过hasRole SpringEL找到。其他一切最终都变成了授权机构。

还有一些其他端点可能缺乏保护或现在无法访问,例如监测和健康端点。取决于它们的配置,它可能会对所有端点产生影响(我只是假设可以通过src / main / application.properties或.yaml中的属性来配置它们,而不使用任何@ Configuration-class。)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。