XSRF-如何设置跨域Cookie

Mac*_*der 5 javascript spring http electron angular

我已经开发了REST API和两个JavaScript客户端(单页应用和本机应用-基于电子)。在这两个客户端中,我的用户都通过OAuth2流进行身份验证:

  1. 发送用户密码到服务器
  2. 获取access_token(以纯文本格式)和refresh_token(以httponly cookie格式)
  3. 当令牌过期时,它们正在刷新它,将请求发送到/ refresh端点(服务器从cookie读取refresh_token)

现在,我想实现csrf保护。所以我在后端(春季)实现了它:

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
                .authorizeRequests().antMatchers("/", "/index.html", "/token/**").permitAll()
                .anyRequest().authenticated();
    }
Run Code Online (Sandbox Code Playgroud)

我的SPA完美运行,Angular从cookie读取XSRF-TOKEN并将其发送到X-XSRF-TOKEN标头中。电子应用程序出现问题。它无权访问Cookie(由于来源不同-电子在file://url 上运行),因此无法设置X-XSRF-TOKEN标头。

我该如何处理?有什么方法可以使“跨域” cookie无效?或者,也许我可以通过电子魔术电子API以某种方式更改cookie的值(如果它可以访问文件系统,也许可以访问在计算机上创建的任何cookie)?

Sbi*_*dan 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);
      }),
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

而我的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 '';
      }
    }));
}
Run Code Online (Sandbox Code Playgroud)