【问题标题】:How to use spring security with POST from html forms?如何使用来自 html 表单的 POST 的 Spring Security?
【发布时间】:2025-12-27 12:55:06
【问题描述】:

我有一个 spring 后端服务并希望允许从 html form 发送 POST 请求。

问题:我在发送 POST 时总是收到403 forbidden。 但是:我可以成功登录应用程序。所以我的身份验证配置一般应该没问题。

也许我缺少我的@PostMapping 控制器的详细信息?我是否必须在该控制器上应用进一步的安全注释?

@Configuration
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
          auth.inMemoryAuthentication()
              .passwordEncoder(NoOpPasswordEncoder.getInstance())
              .withUser("test")
              .password("test")
              .authorities(Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin();
    }
}

我的表单很简单(包含在thymeleaf 模板中):

<form id="edit-form" action="https://localhost:8080/person" method="post">
    <input type="text"...>
    <input type="submit" value="submit" />
</form>
@Controller
public class PersonController {
    @PostMapping("/person")
    public String addItem(Person p) {
        return "OK";
    }
}

调试日志显示:FilterSecurityInterceptor: Authorization successful。虽然我得到了禁止:

2020-11-26 12:21:54.342 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /filter at position 1 of 14 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2020-11-26 12:21:54.342 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /filter at position 2 of 14 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2020-11-26 12:21:54.342 DEBUG 16540 --- [nio-8070-exec-2] w.c.HttpSessionSecurityContextRepository : Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@442b46a2: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@442b46a2: Principal: org.springframework.security.core.userdetails.User@364492: Username: test; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 127.0.0.1; SessionId: F21871A713E04DDC161BC4072F553A68; Granted Authorities: ROLE_USER'
2020-11-26 12:21:54.342 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /filter at position 3 of 14 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2020-11-26 12:21:54.342 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /filter at position 4 of 14 in additional filter chain; firing Filter: 'CsrfFilter'
2020-11-26 12:21:54.342 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.c.CsrfFilter                     : Invalid CSRF token found for http://localhost:8070/filter
2020-11-26 12:21:54.343 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.h.w.HstsHeaderWriter             : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@568a6bb7
2020-11-26 12:21:54.344 DEBUG 16540 --- [nio-8070-exec-2] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
2020-11-26 12:21:54.347 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /error at position 1 of 14 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2020-11-26 12:21:54.347 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /error at position 2 of 14 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2020-11-26 12:21:54.348 DEBUG 16540 --- [nio-8070-exec-2] w.c.HttpSessionSecurityContextRepository : Obtained a valid SecurityContext from SPRING_SECURITY_CONTEXT: 'org.springframework.security.core.context.SecurityContextImpl@442b46a2: Authentication: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@442b46a2: Principal: org.springframework.security.core.userdetails.User@364492: Username: test; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 127.0.0.1; SessionId: F21871A713E04DDC161BC4072F553A68; Granted Authorities: ROLE_USER'
2020-11-26 12:21:54.348 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /error at position 3 of 14 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2020-11-26 12:21:54.348 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /error at position 4 of 14 in additional filter chain; firing Filter: 'CsrfFilter'
2020-11-26 12:21:54.348 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /error at position 5 of 14 in additional filter chain; firing Filter: 'LogoutFilter'
2020-11-26 12:21:54.348 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.u.m.AntPathRequestMatcher        : Checking match of request : '/error'; against '/logout'
2020-11-26 12:21:54.348 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /error at position 6 of 14 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2020-11-26 12:21:54.348 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.u.m.AntPathRequestMatcher        : Checking match of request : '/error'; against '/login'
2020-11-26 12:21:54.348 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /error at position 7 of 14 in additional filter chain; firing Filter: 'DefaultLoginPageGeneratingFilter'
2020-11-26 12:21:54.348 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /error at position 8 of 14 in additional filter chain; firing Filter: 'DefaultLogoutPageGeneratingFilter'
2020-11-26 12:21:54.348 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /error at position 9 of 14 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2020-11-26 12:21:54.348 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.s.HttpSessionRequestCache        : saved request doesn't match
2020-11-26 12:21:54.348 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /error at position 10 of 14 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2020-11-26 12:21:54.348 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /error at position 11 of 14 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2020-11-26 12:21:54.349 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter  : SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@442b46a2: Principal: org.springframework.security.core.userdetails.User@364492: Username: test; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 127.0.0.1; SessionId: F21871A713E04DDC161BC4072F553A68; Granted Authorities: ROLE_USER'
2020-11-26 12:21:54.349 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /error at position 12 of 14 in additional filter chain; firing Filter: 'SessionManagementFilter'
2020-11-26 12:21:54.349 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /error at position 13 of 14 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2020-11-26 12:21:54.349 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /error at position 14 of 14 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2020-11-26 12:21:54.349 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : Secure object: FilterInvocation: URL: /error; Attributes: [authenticated]
2020-11-26 12:21:54.349 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@442b46a2: Principal: org.springframework.security.core.userdetails.User@364492: Username: test; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 127.0.0.1; SessionId: F21871A713E04DDC161BC4072F553A68; Granted Authorities: ROLE_USER
2020-11-26 12:21:54.349 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.a.v.AffirmativeBased               : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@5adc6cf1, returned: 1
2020-11-26 12:21:54.349 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : Authorization successful
2020-11-26 12:21:54.349 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor    : RunAsManager did not change Authentication object
2020-11-26 12:21:54.350 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.FilterChainProxy                 : /error reached end of additional filter chain; proceeding with original chain
2020-11-26 12:21:54.350 DEBUG 16540 --- [nio-8070-exec-2] o.s.w.s.DispatcherServlet                : "ERROR" dispatch for POST "/error", parameters={masked}
2020-11-26 12:21:54.355 DEBUG 16540 --- [nio-8070-exec-2] o.j.s.OpenEntityManagerInViewInterceptor : Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
2020-11-26 12:21:54.358 DEBUG 16540 --- [nio-8070-exec-2] o.s.c.e.PropertySourcesPropertyResolver  : Found key 'spring.template.provider.cache' in PropertySource 'configurationProperties' with value of type String
2020-11-26 12:21:54.362 DEBUG 16540 --- [nio-8070-exec-2] o.s.c.e.PropertySourcesPropertyResolver  : Found key 'spring.template.provider.cache' in PropertySource 'configurationProperties' with value of type String
2020-11-26 12:21:54.367 DEBUG 16540 --- [nio-8070-exec-2] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, text/html;q=0.8]
2020-11-26 12:21:54.369 DEBUG 16540 --- [nio-8070-exec-2] o.j.s.OpenEntityManagerInViewInterceptor : Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
2020-11-26 12:21:54.370 DEBUG 16540 --- [nio-8070-exec-2] o.s.w.s.DispatcherServlet                : Exiting from "ERROR" dispatch, status 403
2020-11-26 12:21:54.371 DEBUG 16540 --- [nio-8070-exec-2] o.s.s.w.a.ExceptionTranslationFilter     : Chain processed normally
2020-11-26 12:21:54.371 DEBUG 16540 --- [nio-8070-exec-2] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed

【问题讨论】:

  • 您确实做到了(您应该在登录后添加permitAll(),但显然可行。您应该添加一个@EnableWebSecurity,以便默认安全规则执行退避。看起来您缺少CSRF东西(默认启用),我怀疑由于您的设置方式,自动添加到表单不起作用。
  • 在使用spring-boot 时我真的必须添加@EnableWebSecurity 我认为如果spring-security 在类路径上,它会通过自动配置添加?至少如果在没有注释的情况下工作,并且在使用 crsf 令牌时。但也许我还是应该添加注释?

标签: java spring spring-boot spring-mvc spring-security


【解决方案1】:

感谢@M。 Deinum 我发现我必须使用th:action 而不是简单的操作字段来定义百里香形式。然后thymeleaf会自动注入crsf字段:

&lt;input type="hidden" name="_csrf" value="25d08979-7785-4131-ac73-a7ce6a16b5ac"&gt;

有了这个,它就可以按预期工作了。

【讨论】:

    最近更新 更多