我有一個單頁的應用程序與Facebook的開發陣營框架,在這裏我使用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);
});
}
}
}
在後端側,我有一個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服務和前端的單頁應用程序。有沒有人有類似的問題?
嘗試創建一個單獨的登錄頁面,實現起來要容易得多:它將包含您的 組件,並且應該打開,即permitAll()。應用程序頁面應該是「認證()」。通過這種方法,您的this.state.sessionState =='LOGGEDIN'邏輯變得多餘。 –
我之前正在使用這種方法,但我覺得這使得代碼更乾淨,因爲我不需要實現一種機制來跟蹤用戶試圖訪問的URL。如果用戶想要轉到https:// domain/task/id並需要先登錄,則採用這種方法會自動運行:首先顯示登錄屏幕,然後顯示目標頁面。我的問題僅限於身份驗證請求。 –
好吧,也許我不清楚你的目標,但我寧願把注意力集中在保持目標網址的問題上,春季安全讓你做到這一點。參見[this](http://stackoverflow.com/questions/14573654/spring-security-redirect-to-previous-page-after-succesful-login)。順便說一句,在客戶端保持授權邏輯給你一種'假'授權,因爲你可以通過瀏覽器中的js調試器來驗證你自己。乾杯! –