Spring 安全 & Angular
Spring security & Angular
我在前端使用 Angular,在后端使用 spring 安全处理安全。
但是,Spring 秒不会对用户进行身份验证。对于有效和无效凭证,其行为是相同的。我想捕获 "bad credential" 无效的用户或密码以及有效凭据的用户数据。
我的问题是什么,我该如何处理?谢谢
spring 安全配置
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public JdbcUserDetailsManager userDetailsManager(AuthenticationManager authenticationManager, DataSource dataSource) {
JdbcUserDetailsManager userDetailsService = new JdbcUserDetailsManager();
userDetailsService.setDataSource(dataSource);
userDetailsService.setAuthenticationManager(authenticationManager);
return userDetailsService;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(passwordEncoder());
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/webjars/**", "/resources/**", "/js/**", "/public/**");
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/login").permitAll().and()
.authorizeRequests().antMatchers("/index").permitAll().and()
.authorizeRequests().anyRequest().hasRole("USER").and()
.exceptionHandling()
.accessDeniedPage("/index?authorization_error=true")
.and()
.csrf()
.csrfTokenRepository(csrfTokenRepository())
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")).disable()
.addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
.logout()
.logoutSuccessUrl("/index")
.logoutUrl("/logout.do")
.and()
.formLogin()
.usernameParameter("j_username")
.passwordParameter("j_password")
.failureUrl("/index?authentication_error=true")
.loginPage("/index")
.loginProcessingUrl("/j_security_check")
.and()
.sessionManagement().maximumSessions(1);
}
private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie == null || token != null
&& !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
};
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
}
Angular 控制器:
var loginService = function () {
var deferred = $q.defer();
$http.post(contextPath + '/j_security_check', {j_username: $scope.credentials.j_username, j_password: $scope.credentials.j_password}).
success(function (data) {
deferred.resolve(data);
}).
error(function (data, status, header, config) {
$log.warn(data, status, header(), config);
deferred.reject(status);
});
return deferred.promise;
};
$scope.login = function () {
loginService().then(function (result) {
console.log(result);
$state.go('dashboard');
}, function (result) {
switch (result) {
case 401:
$scope.message = "Error " + result + ": username or password is not correct";
break;
case 403:
$scope.message = "Error " + result + ": username or password is not correct";
break;
default :
$scope.message = "Error " + result + " :unknown error";
}
})
};
谢谢
更新:
检查这个类似的 SO 问题,其中有示例 angularjs http 拦截器直接获取 csrf 参数并在所有请求中添加 headers。
REASON for default angularJS 不能像 link
中提到的那样工作
默认情况下 AngularJS 提供了一种实现跨站点请求伪造的机制,但是该机制仅适用于 cookie。由于 Spring 安全性是通过将令牌设置为 HTTP 参数来实现的,因此 AngularJS 提供的开箱即用解决方案将不起作用。
如 spring-security-csrf-token-interceptor 项目文档中所述 - "An AngularJS interceptor that sets the Spring Security CSRF token information in all HTTP requests" - 它通过调用 head 来接收 X-CSRF-TOKEN,然后存储此令牌并随每个 http 请求发送出去。
总结:在您的项目中添加上述项目中提到的 angular 拦截器以解决您的问题。检查该 github 项目中提到的示例。
我在前端使用 Angular,在后端使用 spring 安全处理安全。
但是,Spring 秒不会对用户进行身份验证。对于有效和无效凭证,其行为是相同的。我想捕获 "bad credential" 无效的用户或密码以及有效凭据的用户数据。 我的问题是什么,我该如何处理?谢谢
spring 安全配置
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public JdbcUserDetailsManager userDetailsManager(AuthenticationManager authenticationManager, DataSource dataSource) {
JdbcUserDetailsManager userDetailsService = new JdbcUserDetailsManager();
userDetailsService.setDataSource(dataSource);
userDetailsService.setAuthenticationManager(authenticationManager);
return userDetailsService;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(passwordEncoder());
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/webjars/**", "/resources/**", "/js/**", "/public/**");
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/login").permitAll().and()
.authorizeRequests().antMatchers("/index").permitAll().and()
.authorizeRequests().anyRequest().hasRole("USER").and()
.exceptionHandling()
.accessDeniedPage("/index?authorization_error=true")
.and()
.csrf()
.csrfTokenRepository(csrfTokenRepository())
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")).disable()
.addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
.logout()
.logoutSuccessUrl("/index")
.logoutUrl("/logout.do")
.and()
.formLogin()
.usernameParameter("j_username")
.passwordParameter("j_password")
.failureUrl("/index?authentication_error=true")
.loginPage("/index")
.loginProcessingUrl("/j_security_check")
.and()
.sessionManagement().maximumSessions(1);
}
private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie == null || token != null
&& !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
};
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
}
Angular 控制器:
var loginService = function () {
var deferred = $q.defer();
$http.post(contextPath + '/j_security_check', {j_username: $scope.credentials.j_username, j_password: $scope.credentials.j_password}).
success(function (data) {
deferred.resolve(data);
}).
error(function (data, status, header, config) {
$log.warn(data, status, header(), config);
deferred.reject(status);
});
return deferred.promise;
};
$scope.login = function () {
loginService().then(function (result) {
console.log(result);
$state.go('dashboard');
}, function (result) {
switch (result) {
case 401:
$scope.message = "Error " + result + ": username or password is not correct";
break;
case 403:
$scope.message = "Error " + result + ": username or password is not correct";
break;
default :
$scope.message = "Error " + result + " :unknown error";
}
})
};
谢谢
更新:
检查这个类似的 SO 问题,其中有示例 angularjs http 拦截器直接获取 csrf 参数并在所有请求中添加 headers。
REASON for default angularJS 不能像 link
中提到的那样工作默认情况下 AngularJS 提供了一种实现跨站点请求伪造的机制,但是该机制仅适用于 cookie。由于 Spring 安全性是通过将令牌设置为 HTTP 参数来实现的,因此 AngularJS 提供的开箱即用解决方案将不起作用。
如 spring-security-csrf-token-interceptor 项目文档中所述 - "An AngularJS interceptor that sets the Spring Security CSRF token information in all HTTP requests" - 它通过调用 head 来接收 X-CSRF-TOKEN,然后存储此令牌并随每个 http 请求发送出去。
总结:在您的项目中添加上述项目中提到的 angular 拦截器以解决您的问题。检查该 github 项目中提到的示例。