我开发了 REST API 和两个 JavaScript 客户端(单页应用程序和原生应用程序 - 基于 Electron )。在两个客户端中,我的用户都通过 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 header 中。我遇到了 Electron 应用程序的问题。它无权访问 cookie(因为来源不同 - Electron 在
file://
url 上运行),因此无法设置 X-XSRF-TOKEN header 。我该如何处理这样的问题?有没有办法使“跨域”cookie 生效?或者,也许我可以通过 Electron 魔术 Electron API 以某种方式获取 cookie 值(如果它可以访问文件系统,也许它可以访问在机器上创建的任何 cookie)?
最佳答案
我遇到了同样的问题,并最终设法通过实现这样的 Angular 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基本上只是在electron主进程中调用了这个方法:
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 '';
}
}));
}
关于javascript - XSRF - 如何设置跨域 cookie,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41840817/