REST api 的 Spring security 在身份验证失败时显示浏览器弹出窗口

标签 spring rest spring-security reactjs spring-boot

我有一个使用 Facebook 的 React 框架开发的单页应用程序,我在其中使用 JSX 来确定用户是否登录:

render: function() {
    return <div>
      <BrandBar/>
      <div className="container">
        <TopBar/>
        {this.state.sessionState == 'LOADING' ? (<h1>Loading</h1>) : (this.state.sessionState == 'LOGGEDIN' ? this.props.children : <Login/>)}
      </div>
    </div>
}

改变该组件状态的登录函数是一个简单的 REST 调用(使用 superagent),它获取附加了基本身份验证凭据的用户信息:

login: function(username, password){
    return {
      then: function(callback){
        request 
          .get(rootUrl + 'me')
          .auth(username, password)
          .end((err, res) => {
            callback(res);
          });
      }
   }
}

在后端,我在 Spring Boot 中有一个 REST api:

Controller :

@RequestMapping(value = "/me",
        produces = {APPLICATION_JSON},
        method = RequestMethod.GET)
public User getMe() {
    Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    if (principal != null && principal instanceof CurrentUser){
        return ((CurrentUser) principal).getUser();
    }

    return null;
}

@RequestMapping("/stop")
@ResponseStatus(HttpStatus.NO_CONTENT)
public void stop(HttpSession session) {
    session.invalidate();
}

安全配置:

@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable()
                .httpBasic().and()
                .authorizeRequests().anyRequest().authenticated()
                .and().anonymous().disable()
                .exceptionHandling().authenticationEntryPoint(new BasicAuthenticationEntryPoint(){
            @Override
            public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException, ServletException {
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
            }
        });

    }

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .userDetailsService(userDetailsService)
                .passwordEncoder(new BCryptPasswordEncoder());
    }

}

只要我提供的信息正确,登录就可以正常工作,但是当我提供错误的凭据时,服务器会绕过返回普通 401 的异常处理(没有 WWW-Authenticate header ) 。因此,尽管已覆盖 BasicAuthenticationEntryPoint,浏览器仍向我显示弹出窗口。

更奇怪的是,当我在浏览器弹出窗口中提供正确的详细信息时,它仍然返回 401 状态。

这似乎是一个基本设置:一个带有 Spring Security 的简单 REST 服务和前端的单页应用程序。有人遇到过类似的问题吗?

最佳答案

您是否已尝试注册访问被拒绝处理程序?

http.exceptionHandling().accessDeniedHandler(new AccessDeniedHandlerImpl());

public class AccessDeniedHandlerImpl implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse     response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.sendError(HttpStatus.UNAUTHORIZED.value());
    }
}

就像测试当您在安全上下文( Controller 内的代码)中找不到主体时,尝试抛出 AuthenticationException 以查看过滤器链中的某个位置是否处理了异常,应该是这样。

关于REST api 的 Spring security 在身份验证失败时显示浏览器弹出窗口,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33112409/

相关文章:

rest - SharePoint 2013 REST API。过滤系统文件夹和扩展文件夹和文件。

c# - 如何让 ModelState 在 asp.net mvc web api 上工作?

java - 有没有办法缓存 Spring <mvc :resources> files in memory?

spring - 测试数组包含任意顺序的特定对象的jsonpath

rest - 检查 JIRA REST API 版本?

spring-security - spring security thymeleaf LockedException 自定义消息

performance - Spring安全访问控制列表数十亿行

redirect - Backbone.JS "sync"方法中处理 HTTP 302 错误和重定向

java - Spring Security hasRole() 对于未经身份验证的用户,考虑角色层次结构

spring - 将 BASIC 身份验证数据传递到 spring ws 客户端