大家好,我很难为我的应用程序设置安全解决方案!!所以我有一个REST API后端,在http://localhost:51030使用Spring框架开发,对于前端,我有一个Angular 2应用程序(最新版本A.K.A.Angular 4),运行速度为http://localhost:4200.我在后端设置了CORS配置,如下所示:
public class CORSFilter implements Filter
{
// The list of domains allowed to access the server
private final List<String> allowedOrigins = Arrays.asList("http://localhost:4200", "http://127.0.0.1:4200");
public void destroy()
{
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException
{
// Lets make sure that we are working with HTTP (that is, against HttpServletRequest and HttpServletResponse objects)
if (req instanceof HttpServletRequest && res instanceof HttpServletResponse)
{
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// Access-Control-Allow-Origin
String origin = request.getHeader("Origin");
response.setHeader("Access-Control-Allow-Origin", allowedOrigins.contains(origin) ? origin : "");
response.setHeader("Vary", "Origin");
// Access-Control-Max-Age
response.setHeader("Access-Control-Max-Age", "3600");
// Access-Control-Allow-Credentials
response.setHeader("Access-Control-Allow-Credentials", "true");
// Access-Control-Allow-Methods
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
// Access-Control-Allow-Headers
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, " + CSRF.REQUEST_HEADER_NAME); // + CSRF.REQUEST_HEADER_NAME
}
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig)
{
}
}
使用此配置只能正常工作,我可以执行从角应用到回弹的请求并获得响应并执行任何操作。但是当我尝试设置CSRF安全解决方案时,一切都不起作用。这是在后端设置的CSRF和安全配置:
public class CSRF
{
/**
* The name of the cookie with the CSRF token sent by the server as a response.
*/
public static final String RESPONSE_COOKIE_NAME = "XSRF-TOKEN"; //CSRF-TOKEN
/**
* The name of the header carrying the CSRF token, expected in CSRF-protected requests to the server.
*/
public static final String REQUEST_HEADER_NAME = "X-XSRF-TOKEN"; //X-CSRF-TOKEN
// In Angular the CookieXSRFStrategy looks for a cookie called XSRF-TOKEN
// and sets a header named X-XSRF-TOKEN with the value of that cookie.
// The server must do its part by setting the initial XSRF-TOKEN cookie
// and confirming that each subsequent state-modifying request includes
// a matching XSRF-TOKEN cookie and X-XSRF-TOKEN header.
}
public class CSRFTokenResponseCookieBindingFilter extends OncePerRequestFilter
{
protected static final String REQUEST_ATTRIBUTE_NAME = "_csrf";
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException
{
CsrfToken token = (CsrfToken) request.getAttribute(REQUEST_ATTRIBUTE_NAME);
Cookie cookie = new Cookie(CSRF.RESPONSE_COOKIE_NAME, token.getToken());
cookie.setPath("/");
response.addCookie(cookie);
filterChain.doFilter(request, response);
}
}
@Configuration
public class Conf extends WebMvcConfigurerAdapter
{
@Bean
public CORSFilter corsFilter()
{
return new CORSFilter();
}
@Override
public void addViewControllers(ViewControllerRegistry registry)
{
registry.addViewController("/login");
registry.addViewController("/logout");
}
}
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
@Autowired
private RESTAuthenticationEntryPoint authenticationEntryPoint;
@Autowired
private RESTAuthenticationFailureHandler authenticationFailureHandler;
@Autowired
private RESTAuthenticationSuccessHandler authenticationSuccessHandler;
@Autowired
private RESTLogoutSuccessHandler logoutSuccessHandler;
@Resource
private CORSFilter corsFilter;
@Autowired
private DataSource dataSource;
@Autowired
public void globalConfig(AuthenticationManagerBuilder auth) throws Exception
{
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("select login as principal, password as credentials, true from user where login = ?")
.authoritiesByUsernameQuery("select login as principal, profile as role from user where login = ?")
.rolePrefix("ROLE_");
}
@Override
protected void configure(HttpSecurity http) throws Exception
{
//csrf is disabled for the moment
//http.csrf().disable();
//authorized requests
http.authorizeRequests()
.antMatchers("/api/users/**").permitAll()
.antMatchers(HttpMethod.OPTIONS , "/*/**").permitAll()
.antMatchers("/login").permitAll()
.anyRequest().authenticated();
//handling authentication exceptions
http.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint);
//login configuration
http.formLogin()
.loginProcessingUrl("/login")
.successHandler(authenticationSuccessHandler);
http.formLogin()
.failureHandler(authenticationFailureHandler);
//logout configuration
http.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(logoutSuccessHandler);
//CORS configuration
http.addFilterBefore(corsFilter, ChannelProcessingFilter.class);
//CSRF configuration
http.csrf().requireCsrfProtectionMatcher(
new AndRequestMatcher(
// Apply CSRF protection to all paths that do NOT match the ones below
// We disable CSRF at login/logout, but only for OPTIONS methods to enable the browser preflight
new NegatedRequestMatcher(new AntPathRequestMatcher("/login*/**", HttpMethod.OPTIONS.toString())),
new NegatedRequestMatcher(new AntPathRequestMatcher("/logout*/**", HttpMethod.OPTIONS.toString())),
new NegatedRequestMatcher(new AntPathRequestMatcher("/api*/**", HttpMethod.GET.toString())),
new NegatedRequestMatcher(new AntPathRequestMatcher("/api*/**", HttpMethod.HEAD.toString())),
new NegatedRequestMatcher(new AntPathRequestMatcher("/api*/**", HttpMethod.OPTIONS.toString())),
new NegatedRequestMatcher(new AntPathRequestMatcher("/api*/**", HttpMethod.TRACE.toString()))
)
);
// CSRF tokens handling
http.addFilterAfter(new CSRFTokenResponseCookieBindingFilter(), CsrfFilter.class);
}
}
问题是在正面和角4配置,CSRF留档太差,在互联网上没有完整的CSRF实现示例。所以下面是我的登录服务:
@Injectable()
export class LoginService {
private loginUrl = 'http://localhost:51030/login';
constructor(private http: Http) {}
preFlight() {
return this.http.options(this.loginUrl);
}
login(username: string , password: string) {
let headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
let options = new RequestOptions({headers: headers});
let body = "username="+username+"&password="+password;
return this.http.post(this.loginUrl , body , options);
}
}
在登录组件中,我执行ngOnInit生命周期挂钩中的选项请求:
@Component({
templateUrl: './login-layout.component.html'
})
export class LoginLayoutComponent implements OnInit {
credentials = {username: '' , password: ''};
constructor(private loginService: LoginService){}
ngOnInit() {
this.loginService.preFlight()
.subscribe();
}
login() {
this.loginService.login(this.credentials.username , this.credentials.password)
.subscribe(
response=>{
console.log(response) ;
},error=>{
console.log(error);
}
);
}
}
飞行前进行得很顺利,我在options请求上获得了200 OK状态,加上一个临时的JSEEIONID和XSRF-TOKEN Cookie。
因此,在我的应用程序模块中,我添加了这个,如angular docs中所述:
{
provide: XSRFStrategy,
useValue: new CookieXSRFStrategy('XSRF-TOKEN', 'X-XSRF-TOKEN')
},
但是,当我尝试使用凭据执行POST请求或任何后面的请求时,我得到403禁止:“无法验证提供的CSRF令牌,因为找不到您的会话。”
所以,请告诉我如何解决这个问题,有人能给我指出正确的方向吗?因为我不知道该怎么做!!谢谢!!!
我很惊讶你们为CSRF和CORS做了这么多工作,因为Spring Security和Angular内置了支持。Spring Security默认启用CSRF。
Spring Security手册对配置csrf:https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#csrf有很好的留档
谷歌搜索“Angular 2 Spring Security csrf”给出了几个例子(以及我是如何找到你的帖子的)。这里有一个:
https://medium.com/spektrakel-blog/angular2-and-spring-a-friend-in-security-need-is-a-friend-against-csrf-indeed-9f83eaa9ca2e
要解决Spring安全和角度之间的csrf问题,您必须这样做。
在SecurityConfiguration(WebSecurityConfig)中,替换http.csrf(). disable();通过
http.csrf()
.ignoringAntMatchers ("/login","/logout")
.csrfTokenRepository (this.getCsrfTokenRepository());
}
private CsrfTokenRepository getCsrfTokenRepository() {
CookieCsrfTokenRepository tokenRepository = CookieCsrfTokenRepository.withHttpOnlyFalse();
tokenRepository.setCookiePath("/");
return tokenRepository;
{
默认的角csrf拦截器并不总是工作。所以你必须实现你自己的拦截器。
import {Injectable, Inject} from '@angular/core';
import {HttpInterceptor, HttpXsrfTokenExtractor, HttpRequest, HttpHandler,
HttpEvent} from '@angular/common/http';
import {Observable} from "rxjs";
@Injectable()
export class HttpXsrfInterceptor implements HttpInterceptor {
constructor(private tokenExtractor: HttpXsrfTokenExtractor) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
let requestMethod: string = req.method;
requestMethod = requestMethod.toLowerCase();
if (requestMethod && (requestMethod === 'post' || requestMethod === 'delete' || requestMethod === 'put')) {
const headerName = 'X-XSRF-TOKEN';
let 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);
}
}
最后将其添加到您的提供商(app.module.ts)中
providers: [{ provide: HTTP_INTERCEPTORS, useClass: HttpXsrfInterceptor, multi: true }]
考虑一下进口。
HttpClientXsrfModule.withOptions({
cookieName: 'XSRF-TOKEN',
headerName: 'X-CSRF-TOKEN'
}),
问题陈述:我有一些Rest的API,它们使用Spring安全性进行CSRF保护。此外,这些API将通过Angular WEB UI从不同的Origin/domain访问。我不需要Spring Authentication,因为身份验证由Siteminder处理。 方法:我遵循了Dave Syer提供的CSRF保护的链接:登录页面:Angular JS和Spring Security Part II
我正在尝试使用Spring Security(4.1.3)和Angular 2.0.1实现CSRF保护 相关话题的来源很多,但我找不到明确的说明。有些说法甚至相互矛盾。 我读过关于springs的操作方法(尽管指南中描述了Angular 1 way)Spring Security guide,其中包含Angular,即
问题内容: Django随附CSRF保护中间件,该中间件生成用于表单的唯一每次会话令牌。它扫描所有传入的请求以获取正确的令牌,如果令牌丢失或无效,则拒绝该请求。 我想对某些POST请求使用AJAX,但表示请求没有CSRF令牌。这些页面没有任何要钩的元素,我宁可不要弄混将标记作为隐藏值插入的标记。我认为实现此目的的一种好方法是公开vew,以返回用户的令牌,这依赖于浏览器的跨站点脚本编写规则来防止恶意
> 我正在使用OWASP CSRFGuard 3.0保护这些Restful服务不受CSRF的影响。 当使用简单的超文本标记语言访问相同的Rest服务时-AJAX请求-CSRF令牌正在设置,我得到了响应: 下面的代码工作正常。 角度代码(我对角度代码非常陌生) 有人能建议我如何设置角形标记吗。 引自: 在寻找此问题的解决方案时,请阅读以下语句。 跨站请求伪造(XSRF)保护XSRF是一种技术,通过这
重复的步骤 登录 注销 从服务器登录并获取422无法验证CSRF令牌的真实性 Gems 设计3.5.2 设计令牌\u验证0.1.36 根据其他线程,解决方案是在注销时返回一个新的csrf令牌,然后在客户端的注销成功处理程序中,将XSRF-TOKEN的cookie设置为接收的令牌。我使用的代码如下。有人能告诉我为什么它不起作用吗?最后一个登录请求看起来使用了新的令牌,所以棱角分明的看起来像是从coo
就像在本主题中一样,我的Spring Security应用程序也有问题。单击“身份验证”按钮时,即使输入了正确的数据,也会在控制台中看到: 访问位于“”的XMLHttpRequesthttp://localhost:8080/api/v1/basicauth“起源”http://localhost:4200'已被CORS策略阻止:对飞行前请求的响应未通过访问控制检查:它没有HTTP ok状态。 而