TSK-1651: Add XSRF Support (#1602)
* TSK-1651: Add XSRF Support * TSK-1651: now sending XRSF Header for requests with absolute path * TSK-1651: created configuration to enable XSRF for spring-boot example Co-authored-by: Mustapha Zorgati <15628173+mustaphazorgati@users.noreply.github.com>
This commit is contained in:
parent
dd5bccc62c
commit
9b98b56ce4
|
@ -8,6 +8,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
|
|||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
|
||||
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
|
||||
import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
|
||||
|
@ -26,15 +27,18 @@ public class BootWebSecurityConfigurer extends WebSecurityConfigurerAdapter {
|
|||
private final String ldapUserDnPatterns;
|
||||
|
||||
private final boolean devMode;
|
||||
private final boolean enableCsrf;
|
||||
|
||||
public BootWebSecurityConfigurer(
|
||||
@Value("${taskana.ldap.serverUrl:ldap://localhost:10389}") String ldapServerUrl,
|
||||
@Value("${taskana.ldap.baseDn:OU=Test,O=TASKANA}") String ldapBaseDn,
|
||||
@Value("${taskana.ldap.groupSearchBase:cn=groups}") String ldapGroupSearchBase,
|
||||
@Value("${taskana.ldap.userDnPatterns:uid={0},cn=users}") String ldapUserDnPatterns,
|
||||
@Value("${enableCsrf:false}") boolean enableCsrf,
|
||||
LdapAuthoritiesPopulator ldapAuthoritiesPopulator,
|
||||
GrantedAuthoritiesMapper grantedAuthoritiesMapper,
|
||||
@Value("${devMode:false}") boolean devMode) {
|
||||
this.enableCsrf = enableCsrf;
|
||||
this.ldapAuthoritiesPopulator = ldapAuthoritiesPopulator;
|
||||
this.grantedAuthoritiesMapper = grantedAuthoritiesMapper;
|
||||
this.ldapServerUrl = ldapServerUrl;
|
||||
|
@ -60,21 +64,25 @@ public class BootWebSecurityConfigurer extends WebSecurityConfigurerAdapter {
|
|||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
HttpSecurity httpSecurity =
|
||||
http.authorizeRequests()
|
||||
.antMatchers("/css/**", "/img/**")
|
||||
.permitAll()
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
.antMatchers(HttpMethod.GET, "/docs/**")
|
||||
.permitAll()
|
||||
.and()
|
||||
.addFilter(jaasApiIntegrationFilter())
|
||||
.addFilterAfter(new SpringSecurityToJaasFilter(), JaasApiIntegrationFilter.class);
|
||||
|
||||
http.authorizeRequests()
|
||||
.antMatchers("/css/**", "/img/**")
|
||||
.permitAll()
|
||||
.and()
|
||||
.csrf()
|
||||
.disable()
|
||||
.httpBasic()
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
.antMatchers(HttpMethod.GET, "/docs/**")
|
||||
.permitAll()
|
||||
.and()
|
||||
.addFilter(jaasApiIntegrationFilter())
|
||||
.addFilterAfter(new SpringSecurityToJaasFilter(), JaasApiIntegrationFilter.class);
|
||||
if (enableCsrf) {
|
||||
CookieCsrfTokenRepository csrfTokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
|
||||
csrfTokenRepository.setCookiePath("/");
|
||||
httpSecurity.csrf().csrfTokenRepository(csrfTokenRepository);
|
||||
} else {
|
||||
httpSecurity.csrf().disable().httpBasic();
|
||||
}
|
||||
|
||||
if (devMode) {
|
||||
http.headers()
|
||||
|
|
|
@ -31,6 +31,9 @@ taskana.schemaName=TASKANA
|
|||
####### property that control rest api security deploy use true for no security.
|
||||
devMode=false
|
||||
|
||||
# This property enables the support of XSRF tokens. This will not work together with devMode.
|
||||
enableCsrf=true
|
||||
|
||||
####### property that control if the database is cleaned and sample data is generated
|
||||
generateSampleData=true
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { HttpClientModule, HttpClientXsrfModule, HttpXsrfTokenExtractor } from '@angular/common/http';
|
||||
import { NgxsModule } from '@ngxs/store';
|
||||
import { NgxsReduxDevtoolsPluginModule } from '@ngxs/devtools-plugin';
|
||||
import { AlertModule } from 'ngx-bootstrap';
|
||||
|
@ -82,7 +82,8 @@ const MODULES = [
|
|||
MatIconModule,
|
||||
MatSelectModule,
|
||||
NgxsModule.forRoot(STATES, { developmentMode: !environment.production }),
|
||||
NgxsReduxDevtoolsPluginModule.forRoot({ disabled: environment.production, maxAge: 25 })
|
||||
NgxsReduxDevtoolsPluginModule.forRoot({ disabled: environment.production, maxAge: 25 }),
|
||||
HttpClientXsrfModule
|
||||
];
|
||||
|
||||
const DECLARATIONS = [AppComponent, NavBarComponent, UserInformationComponent, NoAccessComponent, SidenavListComponent];
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse } from '@angular/common/http';
|
||||
import {
|
||||
HttpErrorResponse,
|
||||
HttpEvent,
|
||||
HttpHandler,
|
||||
HttpInterceptor,
|
||||
HttpRequest,
|
||||
HttpXsrfTokenExtractor
|
||||
} from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { RequestInProgressService } from 'app/shared/services/request-in-progress/request-in-progress.service';
|
||||
import { environment } from 'environments/environment';
|
||||
|
@ -9,10 +16,18 @@ import { NOTIFICATION_TYPES } from '../../models/notifications';
|
|||
|
||||
@Injectable()
|
||||
export class HttpClientInterceptor implements HttpInterceptor {
|
||||
constructor(private requestInProgressService: RequestInProgressService, private errorsService: NotificationService) {}
|
||||
constructor(
|
||||
private requestInProgressService: RequestInProgressService,
|
||||
private errorsService: NotificationService,
|
||||
private tokenExtractor: HttpXsrfTokenExtractor
|
||||
) {}
|
||||
|
||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
let req = request.clone({ headers: request.headers.set('Content-Type', 'application/hal+json') });
|
||||
let req = request.clone({ setHeaders: { 'Content-Type': 'application/hal+json' } });
|
||||
let token = this.tokenExtractor.getToken() as string;
|
||||
if (token !== null) {
|
||||
req = req.clone({ setHeaders: { 'X-XSRF-TOKEN': token } });
|
||||
}
|
||||
if (!environment.production) {
|
||||
req = req.clone({ headers: req.headers.set('Authorization', 'Basic YWRtaW46YWRtaW4=') });
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue