REST api 的 Spring 安全性在身份验证失败时显示浏览器弹出窗口
Posted
技术标签:
【中文标题】REST api 的 Spring 安全性在身份验证失败时显示浏览器弹出窗口【英文标题】:Spring security for REST api shows the browser popup when auth fails 【发布时间】:2016-01-11 18:41:34 【问题描述】:我有一个使用 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 调用(使用超级代理),它获取附加了基本身份验证凭据的用户信息:
login: function(username, password)
return
then: function(callback)
request
.get(rootUrl + 'me')
.auth(username, password)
.end((err, res) =>
callback(res);
);
在后端,我在 Spring Boot 中有一个 REST api:
控制器:
@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
标头)的异常处理。因此,尽管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());
就像一个测试当您在安全上下文(控制器内的代码)中找不到主体时尝试抛出 AuthenticationException 以查看过滤器链中的某个位置是否处理了异常,应该是的。
【讨论】:
这个没试过,今晚试试。目前,我只有 exceptionHandling().authenticationEntryPoint()【参考方案2】:如果您不想弹出浏览器,最好避免使用401
。
对于 AJAX,我建议使用 403
作为身份验证入口点。
response.sendError(HttpServletResponse.SC_FORBIDDEN)
如果您需要区分“真实”禁止(当用户通过身份验证但不允许访问)和以上,您可以在响应正文中或作为自定义标头传递信息。
【讨论】:
以上是关于REST api 的 Spring 安全性在身份验证失败时显示浏览器弹出窗口的主要内容,如果未能解决你的问题,请参考以下文章
用于非授权连接的 Spring Security REST Api
如何在 Spring Boot Rest api 中创建安全登录控制器
从移动设备登录 Spring Security、Rest api 和 Facebook
在 Spring 安全性中使用 rest 服务进行身份验证和授权 [关闭]