java - 如何在 Springboot 和 Spring Security 中身份验证成功后授权 Rest API 调用

标签 java spring spring-boot spring-security

我有一个使用 Springboot 开发的 Restful API。另外,我还实现了外部 LDAP 身份验证。 http://localhost:8080/login?username=test&password=test通过 ldap 身份验证,并且按预期工作正常。

我的 Spring 安全实现如下。我限制所有 API 调用并且需要进行身份验证。

@Configuration
@EnableWebSecurity
public class ApplicationSecurity extends WebSecurityConfigurerAdapter {


    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
        .csrf().disable()
        .authorizeRequests()
        .antMatchers("/login").permitAll()
        .anyRequest().authenticated()        
        .and().sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    }
...
...
}

我的登录请求有效,但所有 API 调用都未经过身份验证,即使在成功登录后也是如此。我可以看到日志显示 ldap 身份验证成功并创建了 SecurityContext。我的下一个 API 调用没有在上一个登录请求中创建此 SecurityContext。 我的日志如下。

2019-10-11 02:22:31.567 DEBUG 39216 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy : /login?username=test&password=test at position 5 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' 2019-10-11 02:22:31.567 DEBUG 39216 --- [nio-8080-exec-1] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/login'; against '/login' 2019-10-11 02:22:31.567 DEBUG 39216 --- [nio-8080-exec-1] w.a.UsernamePasswordAuthenticationFilter : Request is to process authentication 2019-10-11 02:22:31.570 DEBUG 39216 --- [nio-8080-exec-1] o.s.s.authentication.ProviderManager : Authentication attempt using portal.services.security.CustomActiveDirectoryLdapAuthenticationProvider 2019-10-11 02:22:32.767 DEBUG 39216 --- [nio-8080-exec-1] o.s.s.ldap.SpringSecurityLdapTemplate : Searching for entry under DN '', base = 'dc=abc,dc=com', filter = '(&(objectClass=Person) ((sAMAccountName=12323)))' 2019-10-11 02:22:32.777 DEBUG 39216 --- [nio-8080-exec-1] o.s.s.ldap.SpringSecurityLdapTemplate : Found DN: CN=Test Name,OU=Users,DC=com 2019-10-11 02:22:32.779 INFO 39216 --- [nio-8080-exec-1] o.s.s.ldap.SpringSecurityLdapTemplate : Ignoring PartialResultException 2019-10-11 02:22:32.896 DEBUG 39216 --- [nio-8080-exec-1] o.s.s.l.u.LdapUserDetailsMapper : Mapping user details from context with DN: CN=test name,OU=Users,DC=com 2019-10-11 02:22:32.899 DEBUG 39216 --- [nio-8080-exec-1] s.CompositeSessionAuthenticationStrategy : Delegating to org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy@45a4b042 2019-10-11 02:22:32.899 DEBUG 39216 --- [nio-8080-exec-1] w.a.UsernamePasswordAuthenticationFilter : Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@ff0ce9d1: Principal: org.springframework.security.ldap.userdetails.LdapUserDetailsImpl@7a480d2: Dn: CN=Test name,OU=Users,DC=com; Username: test; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; CredentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ADMIN; Credentials: [PROTECTED]; Authenticated: true; Details: Users; Granted Authorities: ADMIN 2019-10-11 02:22:33.117 DEBUG 39216 --- [nio-8080-exec-1] o.s.s.w.header.writers.HstsHeaderWriter : Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@17741df1 2019-10-11 02:22:33.117 DEBUG 39216 --- [nio-8080-exec-1] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed 2019-10-11 02:22:33.650 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' 2019-10-11 02:22:33.650 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' 2019-10-11 02:22:33.654 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter' 2019-10-11 02:22:33.654 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter' 2019-10-11 02:22:33.654 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', GET] 2019-10-11 02:22:33.655 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'OPTIONS /admin/getCutOffDays' doesn't match 'GET /logout 2019-10-11 02:22:33.655 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', POST] 2019-10-11 02:22:33.655 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'OPTIONS /admin/getCutOffDays' doesn't match 'POST /logout 2019-10-11 02:22:33.655 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', PUT] 2019-10-11 02:22:33.655 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'OPTIONS /admin/getCutOffDays' doesn't match 'PUT /logout 2019-10-11 02:22:33.656 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.web.util.matcher.OrRequestMatcher : Trying to match using Ant [pattern='/logout', DELETE] 2019-10-11 02:22:33.656 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'OPTIONS /admin/getCutOffDays' doesn't match 'DELETE /logout 2019-10-11 02:22:33.656 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.web.util.matcher.OrRequestMatcher : No matches found 2019-10-11 02:22:33.657 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 5 of 11 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' 2019-10-11 02:22:33.657 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Request 'OPTIONS /admin/getCutOffDays' doesn't match 'POST /login 2019-10-11 02:22:33.657 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' 2019-10-11 02:22:33.657 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' 2019-10-11 02:22:33.659 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' 2019-10-11 02:22:33.660 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.a.AnonymousAuthenticationFilter : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@25109219: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS' 2019-10-11 02:22:33.661 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter' 2019-10-11 02:22:33.662 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy : /admin/getCutOffDays at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' 2019-10-11 02:22:33.671 DEBUG 39216 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy
: /admin/getCutOffDays at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' 2019-10-11 02:22:33.673 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/admin/getCutOffDays'; against '/login' 2019-10-11 02:22:33.674 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /admin/getCutOffDays; Attributes: [authenticated] 2019-10-11 02:22:33.674 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@25109219: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS 2019-10-11 02:22:33.688 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@74f28afc, returned: -1 2019-10-11 02:22:33.696 DEBUG 39216 --- [nio-8080-exec-2] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is anonymous); redirecting to authentication entry point

org.springframework.security.access.AccessDeniedException: Access is denied at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.0.8.RELEASE.jar!/:5.0.8.RELEASE] at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-5.0.8.RELEASE.jar!/:5.0.8.RELEASE] at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124) ~[spring-security-web-5.0.8.RELEASE.jar!/:5.0.8.RELEASE] at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) ~[spring-security-web-5.0.8.RELEASE.jar!/:5.0.8.RELEASE]

我期望对/admin/getCutOffDays 的请求应该检索数据,因为它在上一个登录请求中经过了身份验证。

下面是我的 Controller 。

@RequestMapping("/admin")
@RestController
public class AdminController {
    @PreAuthorize("hasAuthority('ADMIN')")
    @GetMapping("/getCutOffDays")
    public long getCutOffDays() {
        return adminService.getSequenceId(CUT_OFF_DAYS);
    }
}

谁能帮我弄清楚我在这里缺少什么。

最佳答案

为了正确回答您的问题,我需要您提供更多信息。我将尝试通过做出一些假设来回答这个问题。

我假设您正在验证您的应用程序,然后进行 REST 调用。首先(正如答案中已经提到的),您有一个无状态 session 策略。这意味着该 session 将无法用于后续的 Http 请求。

您可以通过以下方式处理:

  1. 实现基于 token (透明/不透明)的身份验证。
  2. 实现基本身份验证。

在这两种情况下,对 REST API 的每个请求都需要授权 header (或 Cookie,取决于方法)。

关于java - 如何在 Springboot 和 Spring Security 中身份验证成功后授权 Rest API 调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58338570/

相关文章:

java - 如何将 yml 对象绑定(bind)到声明为该对象实现的接口(interface)的字段?

java - Ant 任务过滤 JAR 中的 zip 文件和 list

java - java编译器会创建多少个文件?

java - 在Spring MVC中获取Windows用户名

java - Spring Boot - 使用自定义 PreAuthorize 表达式和身份验证测试 Rest Api

java - 使用 spring 和 apache tomcat 打印控制台日志的最佳方法是什么? [2018]

spring - Kotlin的ControllerAdvice

java - Quarkus 和 Keycloak/OIDC - NullPointerException

java - 将我的 Java 应用程序连接到 SQL Server 2012

java - Spring Boot SOAP Web 服务的 EndpointNotFound 异常