如何忽略 spring 引导项目中特定 URL 的安全 CSRF
how to ignore spring security CSRF for specific URL's in spring boot project
如何忽略特定 URL 的 CSRF 安全性,例如“/workflow/**”。
除了这个 URL,我需要所有 URL 和方法的授权和 CSRF 安全。
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private RESTAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private RESTAuthenticationFailureHandler authenticationFailureHandler;
@Autowired
private RESTAuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
private PranaUserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().requireCsrfProtectionMatcher(new AllExceptUrlStartedWith("/workflow"))
.and().authorizeRequests()
.antMatchers("/rest/**", "/tasklist").authenticated()
.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/index.html")
.and().exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
.and().formLogin().successHandler(authenticationSuccessHandler)
.and().formLogin().failureHandler(authenticationFailureHandler)
.and().csrf().csrfTokenRepository(csrfTokenRepository()).and().addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
}
private static class AllExceptUrlStartedWith implements RequestMatcher {
private static final String[] ALLOWED_METHODS =
new String[] {"GET"};
private final String[] allowedUrls;
public AllExceptUrlStartedWith(String... allowedUrls) {
this.allowedUrls = allowedUrls;
}
@Override
public boolean matches(HttpServletRequest request) {
String method = request.getMethod();
for(String allowedMethod : ALLOWED_METHODS) {
if (allowedMethod.equals(method)) {
return false;
}
}
String uri = request.getRequestURI();
for (String allowedUrl : allowedUrls) {
if (uri.startsWith(allowedUrl)) {
return false;
}
}
return true;
}
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/styles/**").antMatchers("/scripts/**");
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
}
如何忽略特定 URL 的 CSRF 安全性,例如“/workflow/**”。
除了这个 URL,我需要所有 URL 和方法的授权和 CSRF 安全。
在我的项目中,我使用了以下代码:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
...
.csrf()
// Allow unsecured requests to H2 console
.requireCsrfProtectionMatcher(new AllExceptUrlsStartedWith("/console"))
...
}
private static class AllExceptUrlsStartedWith implements RequestMatcher {
private static final String[] ALLOWED_METHODS =
new String[] {"GET", "HEAD", "TRACE", "OPTIONS"};
private final String[] allowedUrls;
public AllExceptUrlsStartedWith(String... allowedUrls) {
this.allowedUrls = allowedUrls;
}
@Override
public boolean matches(HttpServletRequest request) {
// replicate default behavior (see CsrfFilter.DefaultRequiresCsrfMatcher class)
String method = request.getMethod();
for (String allowedMethod : ALLOWED_METHODS) {
if (allowedMethod.equals(method)) {
return false;
}
}
// apply our own exceptions
String uri = request.getRequestURI();
for (String allowedUrl : allowedUrls) {
if (uri.startsWith(allowedUrl)) {
return false;
}
}
return true;
}
}
在此示例中,我为 /console
禁用了 CSRF 保护。
更新:since Spring Security 4.0 you can simplify it to a single line:
csrf()
.ignoringAntMatchers("/nocsrf","/ignore/startswith/**")
回答我自己的问题...感谢@Slava
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private RESTAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private RESTAuthenticationFailureHandler authenticationFailureHandler;
@Autowired
private RESTAuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
private PranaUserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().requireCsrfProtectionMatcher(new AllExceptUrlStartedWith("/workflow"))
.and().authorizeRequests()
.antMatchers("/rest/**", "/tasklist").authenticated()
.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/index.html")
.and().exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
.and().formLogin().successHandler(authenticationSuccessHandler)
.and().formLogin().failureHandler(authenticationFailureHandler)
.and().csrf().csrfTokenRepository(csrfTokenRepository()).and().addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
}
private static class AllExceptUrlStartedWith implements RequestMatcher {
private static final String[] ALLOWED_METHODS =
new String[] {"GET"};
private final String[] allowedUrls;
public AllExceptUrlStartedWith(String... allowedUrls) {
this.allowedUrls = allowedUrls;
}
@Override
public boolean matches(HttpServletRequest request) {
String method = request.getMethod();
for(String allowedMethod : ALLOWED_METHODS) {
if (allowedMethod.equals(method)) {
return false;
}
}
String uri = request.getRequestURI();
for (String allowedUrl : allowedUrls) {
if (uri.startsWith(allowedUrl)) {
return false;
}
}
return true;
}
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/styles/**").antMatchers("/scripts/**");
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
}
在这个帖子里回答的唯一目的就是解释和使用antPathMatcher
,其优点可以用来保护许多带有蚂蚁匹配器的url。
来自文档
.csrf().requireCsrfProtectionMatcher(RequestMatcher requireCsrfProtectionMatcher)
Specify the RequestMatcher to use for determining when CSRF should be applied. The default is to ignore GET, HEAD, TRACE, OPTIONS and process all other requests.
请注意,默认情况下 GET
、HEAD
、TRACE
、OPTIONS
请求将被忽略。如果你想覆盖这个默认配置 requireCsrfProtectionMatcher(implementation_of_RequestMatcher)
。
在 RequestMatcher 的实现中定义所有需要保护的 URL。 你完成了
假设您希望 URL 的 /api/**
得到 CSRF 保护.
@Autowired
RequestMatcher csrfProtectedMatchers;
@Override
protected void configure(final HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.antMatchers("/resources/**", "/", "/login").permitAll()
.antMatchers("/api/**").hasAnyRole("ADMIN", "USER")
.antMatchers("/app/user/*")
.hasAnyRole("ADMIN", "USER")
.and().formLogin()
.and().csrf().requireCsrfProtectionMatcher(csrfProtectedMatchers);
}
@Bean
public RequestMatcher getCsrfProtectedMatchers()
{
UrlPathHelper urlPathHelper = new UrlPathHelper();
AntPathMatcher antPathMatcher = new AntPathMatcher();
List<String> protectedUrlPatterns = Arrays.asList("/api/**", "/logout");
return new RequestMatcher()
{
@Override
public boolean matches(HttpServletRequest request)
{
String uri = urlPathHelper.getPathWithinApplication(request);
for (String pattern : protectedUrlPatterns)
{
if (antPathMatcher.match(pattern, uri))
{
return true;
}
}
return false;
}
};
}
逻辑解释
假设 URL: http://localhost:8080/csrf/api/test1
String uri = urlPathHelper.getPathWithinApplication(request);
uri => /api/test1
;
antPathMatcher.match("/api/**", "/api/test1")
=> true
如何忽略特定 URL 的 CSRF 安全性,例如“/workflow/**”。 除了这个 URL,我需要所有 URL 和方法的授权和 CSRF 安全。
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private RESTAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private RESTAuthenticationFailureHandler authenticationFailureHandler;
@Autowired
private RESTAuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
private PranaUserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().requireCsrfProtectionMatcher(new AllExceptUrlStartedWith("/workflow"))
.and().authorizeRequests()
.antMatchers("/rest/**", "/tasklist").authenticated()
.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/index.html")
.and().exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
.and().formLogin().successHandler(authenticationSuccessHandler)
.and().formLogin().failureHandler(authenticationFailureHandler)
.and().csrf().csrfTokenRepository(csrfTokenRepository()).and().addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
}
private static class AllExceptUrlStartedWith implements RequestMatcher {
private static final String[] ALLOWED_METHODS =
new String[] {"GET"};
private final String[] allowedUrls;
public AllExceptUrlStartedWith(String... allowedUrls) {
this.allowedUrls = allowedUrls;
}
@Override
public boolean matches(HttpServletRequest request) {
String method = request.getMethod();
for(String allowedMethod : ALLOWED_METHODS) {
if (allowedMethod.equals(method)) {
return false;
}
}
String uri = request.getRequestURI();
for (String allowedUrl : allowedUrls) {
if (uri.startsWith(allowedUrl)) {
return false;
}
}
return true;
}
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/styles/**").antMatchers("/scripts/**");
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
}
如何忽略特定 URL 的 CSRF 安全性,例如“/workflow/**”。 除了这个 URL,我需要所有 URL 和方法的授权和 CSRF 安全。
在我的项目中,我使用了以下代码:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
...
.csrf()
// Allow unsecured requests to H2 console
.requireCsrfProtectionMatcher(new AllExceptUrlsStartedWith("/console"))
...
}
private static class AllExceptUrlsStartedWith implements RequestMatcher {
private static final String[] ALLOWED_METHODS =
new String[] {"GET", "HEAD", "TRACE", "OPTIONS"};
private final String[] allowedUrls;
public AllExceptUrlsStartedWith(String... allowedUrls) {
this.allowedUrls = allowedUrls;
}
@Override
public boolean matches(HttpServletRequest request) {
// replicate default behavior (see CsrfFilter.DefaultRequiresCsrfMatcher class)
String method = request.getMethod();
for (String allowedMethod : ALLOWED_METHODS) {
if (allowedMethod.equals(method)) {
return false;
}
}
// apply our own exceptions
String uri = request.getRequestURI();
for (String allowedUrl : allowedUrls) {
if (uri.startsWith(allowedUrl)) {
return false;
}
}
return true;
}
}
在此示例中,我为 /console
禁用了 CSRF 保护。
更新:since Spring Security 4.0 you can simplify it to a single line:
csrf()
.ignoringAntMatchers("/nocsrf","/ignore/startswith/**")
回答我自己的问题...感谢@Slava
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private RESTAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private RESTAuthenticationFailureHandler authenticationFailureHandler;
@Autowired
private RESTAuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
private PranaUserDetailsService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().requireCsrfProtectionMatcher(new AllExceptUrlStartedWith("/workflow"))
.and().authorizeRequests()
.antMatchers("/rest/**", "/tasklist").authenticated()
.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/index.html")
.and().exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
.and().formLogin().successHandler(authenticationSuccessHandler)
.and().formLogin().failureHandler(authenticationFailureHandler)
.and().csrf().csrfTokenRepository(csrfTokenRepository()).and().addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);
}
private static class AllExceptUrlStartedWith implements RequestMatcher {
private static final String[] ALLOWED_METHODS =
new String[] {"GET"};
private final String[] allowedUrls;
public AllExceptUrlStartedWith(String... allowedUrls) {
this.allowedUrls = allowedUrls;
}
@Override
public boolean matches(HttpServletRequest request) {
String method = request.getMethod();
for(String allowedMethod : ALLOWED_METHODS) {
if (allowedMethod.equals(method)) {
return false;
}
}
String uri = request.getRequestURI();
for (String allowedUrl : allowedUrls) {
if (uri.startsWith(allowedUrl)) {
return false;
}
}
return true;
}
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/styles/**").antMatchers("/scripts/**");
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
}
在这个帖子里回答的唯一目的就是解释和使用antPathMatcher
,其优点可以用来保护许多带有蚂蚁匹配器的url。
来自文档
.csrf().requireCsrfProtectionMatcher(RequestMatcher requireCsrfProtectionMatcher)
Specify the RequestMatcher to use for determining when CSRF should be applied. The default is to ignore GET, HEAD, TRACE, OPTIONS and process all other requests.
请注意,默认情况下 GET
、HEAD
、TRACE
、OPTIONS
请求将被忽略。如果你想覆盖这个默认配置 requireCsrfProtectionMatcher(implementation_of_RequestMatcher)
。
在 RequestMatcher 的实现中定义所有需要保护的 URL。 你完成了
假设您希望 URL 的 /api/**
得到 CSRF 保护.
@Autowired
RequestMatcher csrfProtectedMatchers;
@Override
protected void configure(final HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.antMatchers("/resources/**", "/", "/login").permitAll()
.antMatchers("/api/**").hasAnyRole("ADMIN", "USER")
.antMatchers("/app/user/*")
.hasAnyRole("ADMIN", "USER")
.and().formLogin()
.and().csrf().requireCsrfProtectionMatcher(csrfProtectedMatchers);
}
@Bean
public RequestMatcher getCsrfProtectedMatchers()
{
UrlPathHelper urlPathHelper = new UrlPathHelper();
AntPathMatcher antPathMatcher = new AntPathMatcher();
List<String> protectedUrlPatterns = Arrays.asList("/api/**", "/logout");
return new RequestMatcher()
{
@Override
public boolean matches(HttpServletRequest request)
{
String uri = urlPathHelper.getPathWithinApplication(request);
for (String pattern : protectedUrlPatterns)
{
if (antPathMatcher.match(pattern, uri))
{
return true;
}
}
return false;
}
};
}
逻辑解释
假设 URL: http://localhost:8080/csrf/api/test1
String uri = urlPathHelper.getPathWithinApplication(request);
uri => /api/test1
;
antPathMatcher.match("/api/**", "/api/test1")
=> true