早上好我正在为spring安全的过滤链和安全配置而挣扎
@Configuration
public class SecurityConfiguration {
@Autowired
private CustomHeaderVerificationFilter customHeaderFilter;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.addFilterBefore(customHeaderFilter, BasicAuthenticationFilter.class)
.authorizeRequests()
.requestMatchers(HttpMethod.GET, "/myapp/login").permitAll()
.anyRequest().permitAll();;
return http.build();
}
}
正如你所看到的,逻辑将是这样的,每个调用都将被customHeaderFilter过滤,然后如果调用来自myapp/login作为httpGET,我将允许,不需要其他身份验证,否则...我允许所有(原因在前面)
@Component
public class CustomHeaderVerificationFilter extends OncePerRequestFilter {
@Autowired
Dao engine;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String headerValue = request.getHeader("Authorization");
try {
if (headerValue != null && calculateMatch(headerValue.split("Bearer:")[1],request.getHeader("realmName"))) {
filterChain.doFilter(request, response);
} else {
throw new NullPointerException();
}
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
} catch (NullPointerException e2){
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json");
response.getWriter().write("Errore credenziali errate");
}
}
private boolean calculateMatch(String fromFront,String realmNameHeader) throws NoSuchAlgorithmException,NullPointerException {
//prendo la secretdalBack
String realmSecret = engine.getSecret(realmNameHeader);
MessageDigest digest = MessageDigest.getInstance("SHA-256");
String input = realmSecret + ":" + realmNameHeader;
byte[] hashBytes = digest.digest(input.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : hashBytes) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
String s = hexString.toString();
return fromFront.equals(hexString.toString());
}
}
(一个非常基本的非JWT承载过滤器,我想这不是问题所在)。
然而,我使用的每一个post调用,我都会收到一个未经授权的403错误。CSRF应该是“问题”,我发现的所有文档,他们只是跳过它禁用:但我会掌握它,并集成在我的应用程序。我不明白我的POST是否必须在GET调用之前请求csrf令牌,或者在调用的握手部分完成。我测试了各种方法,但其中很多都是utilyze .csrf(),它被弃用了,也有自定义过滤器,他们只是检查长度,但出于一个有趣的原因,只有我的get会进入这个过滤器。那么,流程中的错误在哪里?我需要通过逻辑检查CSRF滤波器?我必须保存它作为jwt代币吗?
1条答案
按热度按时间2ledvvac1#
你面对的错误是由于csrf配置,你需要在所有不安全的请求中有csrf令牌(任何改变状态的请求)
CSRF攻击之所以有效,是因为浏览器请求自动包含所有Cookie,包括会话Cookie。因此,如果用户通过了网站的身份验证,并且用户进入了一个邪恶的网站,这个邪恶的网站可以向我们的网站发送一个帖子请求(做任何事情),我们的网站无法区分合法的授权请求和伪造的身份验证请求。所以我们想给予用户一个唯一的令牌,他可以保存(远离cookie),用户在每个不安全的请求(即任何改变状态的请求)中使用该令牌。
何时以及如何获得CSRF代币?
1-在Spring Security 5中,默认行为是CsrfToken将在每个响应上加载。因此,默认情况下,您会在来自服务器的每个响应中获得一个XSRF-TOKEN cookie。
2-在Spring Security 6中,默认情况下,CsrfToken的查找将被推迟,直到需要它。所以cookie不会被设置,除非你发送一个状态更改请求(post,put,...),你可以克服这个问题,并使用以下配置为每个请求获取csrfToken。
3-此外,您可以有一个返回csrf令牌的端点,并在需要时点击它。像这样
所有3种都是可接受的解决方案。在第一个和第二个中,你从cookie中获取XSRF-TOKEN,在第三个中,你从响应主体中获取令牌,然后将其用作下一个不安全请求的X-CSRF-TOKEN头。
链接可能有助于:
cookieToHeader
https://docs.spring.io/spring-security/reference/features/exploits/csrf.html
https://docs.spring.io/spring-security/reference/5.8/migration/servlet/exploits.html#_defer_loading_csrftoken