我使用的是Spring 4.3.12。发行版AngularJS 1.4.8。我正试图阻止对应用程序的CSRF攻击。
@Configuration
@Order(2)
public static class SecurityConfig extends WebSecurityConfigurerAdapter {
String[] pathsToRemoveAuthorizaton = {
"/mobile/**",
"/logout",
"/j_spring_security_logout",
"/login",
};
private final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
@Override
public void configure(HttpSecurity http) throws Exception {
logger.info("http configure");
http.antMatcher("/**").authorizeRequests().antMatchers(pathsToRemoveAuthorizaton).permitAll()
.antMatchers("/**").authenticated()
.and().formLogin().loginPage("/login")
.usernameParameter("employeeId").passwordParameter("password")
.successForwardUrl("/dashboard").defaultSuccessUrl("/dashboard", true)
.successHandler(customAuthenticationSuccessHandler()).loginProcessingUrl("/j_spring_security_check")
.and().logout().logoutSuccessUrl("/logout").logoutUrl("/j_spring_security_logout")
.logoutSuccessHandler(customLogoutSuccessHandler()).permitAll().invalidateHttpSession(true)
.deleteCookies("JSESSIONID").and().sessionManagement().sessionFixation().newSession()
.maximumSessions(1).maxSessionsPreventsLogin(true).and()
.sessionCreationPolicy(SessionCreationPolicy.NEVER).invalidSessionUrl("/logout").and()
.exceptionHandling().accessDeniedPage("/logout");
// http.csrf().csrfTokenRepository(csrfTokenRepository()).and()
// .addFilterAfter(new StatelessCSRFFilter(), CsrfFilter.class);
http.csrf().csrfTokenRepository(csrfTokenRepository());
// http.csrf().disable();
// http.csrf().ignoringAntMatchers("/mobile/**");
http.authorizeRequests().anyRequest().authenticated();
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
@Bean
public AuthenticationSuccessHandler customAuthenticationSuccessHandler() {
return new CustomAuthenticationSuccessHandler();
}
@Bean
public LogoutSuccessHandler customLogoutSuccessHandler() {
return new CustomLogoutSuccessHandler();
}
}
下面是我的角服务代码
govtPMS.service('Interceptor', function($q, $location, $rootScope, pinesNotifications, Auth) {
return {
request: function(config) {
config.headers.Authorization = 'Bearer '+$rootScope.authToken;
// document.cookie = 'CSRF-TOKEN=' + $rootScope.generateKey;
return config;
},
requestError: function (rejection) {
return $q.reject(rejection);
},
response: function(res) {
if(res.status === 200 || res.status === 201){
if(res.data.response !== undefined){
if(res.data.status === 1 || res.data.status === 3 || res.data.status === 2) {
pinesNotifications.notify({
'title': 'Success',
'text': res.data.message,
'type': 'success',
'delay': 5000
});
}
else if(res.data.status === 5) {
pinesNotifications.notify({
'title': 'Warning',
'text': res.data.message,
'type': 'warning',
'delay': 5000
});
}
}
}
return res || $q.when(res);
},
responseError: function(error) {
return $q.reject(error);
}
};
}).config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.xsrfHeaderName = 'X-CSRF-TOKEN';
$httpProvider.defaults.xsrfCookieName = 'CSRF-TOKEN';
$httpProvider.interceptors.push('Interceptor');
}])
我仍然无法看到CSRF令牌标头和请求。
<li><a href="j_spring_security_logout" ><i class="fa fa-sign-out"></i><span>Logout</span></a></li>
statelessCSRFFilter.java
package com.leadwinner.sms.config.filters;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.access.AccessDeniedHandlerImpl;
import org.springframework.web.filter.OncePerRequestFilter;
public class StatelessCSRFFilter extends OncePerRequestFilter {
private static final String CSRF_TOKEN = "CSRF-TOKEN";
private static final String X_CSRF_TOKEN = "X-CSRF-TOKEN";
private final AccessDeniedHandler accessDeniedHandler = new AccessDeniedHandlerImpl();
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
List<String> excludedUrls = new ArrayList<>();
excludedUrls.add("/resources");
excludedUrls.add("/j_spring_security_check");
excludedUrls.add("/j_spring_security_logout");
excludedUrls.add("/login");
excludedUrls.add("/logout");
excludedUrls.add("/mobile");
excludedUrls.add("/migrate");
excludedUrls.add("/dashboard");
String path = request.getServletPath();
System.out.println(path);
AtomicBoolean ignoreUrl = new AtomicBoolean(false);
excludedUrls.forEach(url -> {
if (request.getServletPath().startsWith(url.toLowerCase()) || request.getServletPath().equals("/")) {
ignoreUrl.set(true);
}
});
if (!ignoreUrl.get()) {
final String csrfTokenValue = request.getHeader(X_CSRF_TOKEN);
final Cookie[] cookies = request.getCookies();
System.out.println("**************************************************");
System.out.println("--------------------------------------------------");
String csrfCookieValue = null;
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals(CSRF_TOKEN)) {
csrfCookieValue = cookie.getValue();
}
}
}
System.out.println("csrfTokenValue = "+csrfTokenValue);
System.out.println("csrfCookieValue = "+csrfCookieValue);
System.out.println("--------------------------------------------------");
System.out.println("**************************************************");
if (csrfTokenValue == null || !csrfTokenValue.equals(csrfCookieValue)) {
accessDeniedHandler.handle(request, response, new AccessDeniedException(
"Missing or non-matching CSRF-token"));
return;
}
}
filterChain.doFilter(request, response);
}
}
如果请求可以由浏览器发出,并且凭据可以自动提交(会话cookie,基本auth creds),那么CSRF保护是必要的,即使使用移动API也是如此。
如果您有一个移动API作为应用程序的一部分,那么问题是浏览器能否成功地处理这些API?
我建议您创建两个独立的过滤链,如下所示,一个用于web应用程序,一个用于移动API:
@Configuration
@Order(100)
public class WebAppConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) {
http
.requestMatchers()
.antMatchers("/app/**")
.and()
.authorizeRequests()
// ...
.anyRequest().authenticated()
.and()
.formLogin();
}
}
@Configuration
@Order(101)
public class MobileApiConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) {
http
.requestMatchers()
.antMatchers("/api/**")
.and()
.authorizeRequests()
// ...
.anyRequest().authenticated()
.and()
.oauth2ResourceServer()
.jwt();
}
}
这样做的目的是将两种配置分开。相对于web应用程序的endpoint使用一种设置,而相对于移动API的endpoint使用另一种设置。
现在,对移动API做几点评论。我假设您正在使用OAuth2.0承载令牌进行身份验证,这就是为什么上面的配置使用Spring Security 5.1+中的oauth2Resourceserver()
。这样做的是有选择地禁用包含Authorization:Bearer xyz
标头的请求的CSRF。
但是,由于您使用的是Spring Security4.3,那么您可能需要执行以下操作(除非您可以升级):
java prettyprint-override">@Order(101)
public class MobileApiConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) {
http
.requestMatchers()
.antMatchers("/api/**")
.and()
.authorizeRequests()
// ...
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(NEVER)
.and()
.addFilterBefore(new MyMobileAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.csrf().disable();
}
}
不过,您需要确保的是,自定义身份验证筛选器不使用浏览器从任何来源(会话cookies,Authorization:basic
)自动发送的身份验证机制。
我正在设置Angular Spring Security模块来登录和注册用户。当我注册一个用户时,一切都正常。注册后的最后一步是自动登录,但我遇到了以下错误: XMLHttpRequest无法加载超文本传输协议//localhost:8080/com-tesis/login.请求的资源上不存在“访问控制允许起源”标头。因此不允许访问起源“超文本传输协议//localhost:9000”。响应的HT
我正在学习springsecurity(基于java的配置),我无法使注销正常工作。当我点击注销时,我看到URL更改为http://localhost:8080/logout并获取“HTTP 404-/logout”。登录功能工作正常(即使使用自定义登录表单),但问题是注销,我怀疑重定向的url“localhost:8080/logout”应该类似于“localhost:8808/springte
什么是CSRF CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。 那么CSRF到底能够干嘛呢?你可以这样简单的理解:攻击者可以盗用你的登陆信息,以你的身份模拟发送各种请求。攻击者只要借助少许的社会工程学的诡计,例如通过QQ等聊天软件发送的链接(有些还伪装成
主要内容:1.相互排斥,2.保持并等待,4.循环等待如果我们用一个站在四条腿上的桌子来模拟死锁,那么也可以用同时发生的四个条件来模拟四条腿,导致死锁。 但是,如果我们破坏桌子的一条腿,那么桌子肯定会掉下来。如果能够违反四种必要条件之一并且不让它们一起出现,那么就可以防止死锁,这同样发生在死锁上。 下面来看看如何防止每个条件的发生。 1.相互排斥 从资源的角度看,相互关联的部分是资源永远不能同时被多个进程使用,这是公平的,但这是造成死锁的主要原因。如
问题内容: 有一个Node.js项目用于清理数据,还有一个用于JavaScript的OWASP库,用于处理清理过程以防止XSS。 我一直在对这些库进行基准测试,它们非常密集,也许是一个过大的杀伤力,我的应用程序不需要任何动态HTML(由用户,bbtags提交,甚至根本不需要,都不需要),所以为什么不这样做呢: 禁用“ ”和“ ”字符,不要替换它们或其他任何东西,只需禁用它们,如果用户提交了这些,则
目前,我正在使用以下内容将用户登录到我的应用程序中。然而,我想使用一个角函数来实际执行登录。为此,我想创建一个Rest网络服务来进行身份验证,但是我在SO上看到的所有示例都使用我认为被贬低的用户。我还希望该服务返回有关用户的信息。 我要问的是如何将MyUserDetailsService更改为用作登录的restful服务,或者如何创建一个可用于登录的服务,该服务将在登录后返回用户对象。 这是我的a