我开发了REST API和两个JavaScript客户端(基于电子的单页应用程序和本机应用程序)。在两个客户端中,我的用户都通过OAuth2流进行身份验证:
现在我想实现csrf保护。所以我在我的后端(Spring)实现了它:
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.authorizeRequests().antMatchers("/", "/index.html", "/token/**").permitAll()
.anyRequest().authenticated();
}
我的SPA工作正常,angular从cookie读取XSRF-TOKEN并以X-XSRF-TOKEN标头发送。我遇到了电子应用的问题。它无法访问cookie(由于来源不同 - 电子在file://
url上运行),因此无法设置X-XSRF-TOKEN标头。
我该如何处理这个问题?有什么方法可以实现"交叉起源"曲奇饼?或者也许我可以通过电子魔术电子API获取cookie值(如果它可以访问文件系统,也许它可以访问在机器上创建的任何cookie)?
答案 0 :(得分:0)
我遇到了同样的问题,最终设法通过实现一个有角度的http拦截器来解决此问题:
@Injectable()
export class HttpXsrfInterceptor implements HttpInterceptor {
constructor(private tokenExtractor: HttpXsrfTokenExtractor, //from angular
private nativeAuthService: NativeAuthService) { //my native service
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
//this works in web
const headerName = 'X-XSRF-TOKEN';
const token = this.tokenExtractor.getToken() as string;
if (token !== null && !req.headers.has(headerName)) {
req = req.clone({ headers: req.headers.set(headerName, token) });
return next.handle(req);
}
//this works in electron
return this.nativeAuthService.getCookieValue('XSRF-TOKEN').pipe(
mergeMap((xsrfToken: string) => {
if (xsrfToken && !req.headers.has(headerName)) {
req = req.clone({ headers: req.headers.set(headerName, xsrfToken) });
}
return next.handle(req);
}),
);
}
}
我的nativeAuthService基本上只是在电子主过程中调用此方法:
export function getCookieValue(cookieName: string): Observable<string> {
return from(session.defaultSession.cookies.get({ name: cookieName })
.then((cookies: Electron.Cookie[]) => {
if (cookies.length == 1) {
return cookies[0].value;
} else {
if (cookies.length > 1) {
throw Error(`There is more than one cookie with the name: ${ cookieName }.`);
}
return '';
}
}));
}