Keycloak:AnonymousAuthenticationToken无法强制转换为KeycloakAuthenticationToken

时间:2018-02-16 09:53:19

标签: java spring spring-security microservices keycloak

我正在开发基于Spring Cloud的微服务基础架构。我想用Keycloak保护应用程序,如果用户通过身份验证,它基本上可以正常工作。

如果用户未经过身份验证,Keycloak会抛出以下错误:

if(get_post_meta($post->ID, '_bv_faq_thumbs_up', true) === null) {
    $bv_faq_thumbs_up = 0;
} else {
    $bv_faq_thumbs_up = get_post_meta($post->ID, '_bv_faq_thumbs_up', true);
}

安全配置如下所示:

java.lang.ClassCastException: org.springframework.security.authentication.AnonymousAuthenticationToken cannot be cast to org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken
at org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade.getSecurityContext(SimpleHttpFacade.java:63) ~[keycloak-spring-security-adapter-3.4.3.Final.jar:3.4.3.Final]
at org.keycloak.adapters.AuthenticatedActionsHandler.corsRequest(AuthenticatedActionsHandler.java:102) ~[keycloak-adapter-core-3.4.3.Final.jar:3.4.3.Final]
at org.keycloak.adapters.AuthenticatedActionsHandler.handledRequest(AuthenticatedActionsHandler.java:54) ~[keycloak-adapter-core-3.4.3.Final.jar:3.4.3.Final]
at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:78) ~[keycloak-spring-security-adapter-3.4.3.Final.jar:3.4.3.Final]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.java:110) ~[spring-boot-actuator-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.java:79) ~[keycloak-spring-security-adapter-3.4.3.Final.jar:3.4.3.Final]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.java:82) ~[keycloak-spring-security-adapter-3.4.3.Final.jar:3.4.3.Final]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:84) ~[keycloak-spring-security-adapter-3.4.3.Final.jar:3.4.3.Final]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:347) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:263) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106) ~[spring-boot-actuator-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve.invoke(AbstractAuthenticatedActionsValve.java:67) [spring-boot-container-bundle-3.4.3.Final.jar:3.4.3.Final]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:595) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.java:181) [spring-boot-container-bundle-3.4.3.Final.jar:3.4.3.Final]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.23.jar:8.5.23]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.23.jar:8.5.23]
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.8.0_144]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.8.0_144]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.23.jar:8.5.23]
at java.lang.Thread.run(Unknown Source) [na:1.8.0_144]

任何建议都会受到很多关注。

亲切的问候 Blacky

8 个答案:

答案 0 :(得分:1)

我有同样的问题。

将keycloak客户端更改为bearer-only并未解决问题。

存在的问题是公共端点。

@Override
protected void configure( HttpSecurity http ) throws Exception {
    super.configure( http );
    http
        .csrf().disable()
        .sessionManagement()
        .sessionCreationPolicy( SessionCreationPolicy.STATELESS )
        .and()
        .requestMatchers()
        .and()
        .authorizeRequests()
        .antMatchers( "/tenants**" ).permitAll() // <- public endpoint
        .anyRequest()
        .authenticated();
}

对于这些端点,spring security会为虚拟用户&#34; anonymousUser创建一个匿名身份验证。&#34;此身份验证是AnonymousAuthenticationToken的一个实例,无法将其转换为KeycloakAuthenticationToken。

如果您尝试从经过身份验证的客户端(例如角度应用程序)发出请求,它将起作用,因为它可以通过授权标头上发送的令牌解析身份验证。这就是仅限承载方法在相同情况下起作用的原因。

我想向后端发出请求以获得正确的领域以在角度方面进行身份验证。在那一刻,我没有任何身份验证令牌要发送,因此Spring安全性将创建匿名身份验证。

仅在keycloak.cors = true时抛出异常。

当通过方法corsRequest()在类AuthenticatedActionsHandler.class上调用SimpleHttpFacade.class的方法getSecurityContext()时,会出现问题。

有没有人有工作解决方案?

最好的问候

答案 1 :(得分:0)

我的微服务架构遇到了同样的问题。 根据Stian Thorgersen的这个this回答,所有ReST-Services都应该只是持票人。因此,他们应该接受令牌,但从不执行重定向到登录页面。

因此,我从服务中提取了UI组件,并在单独的NGINX实例上提供它。 UI执行重定向到我的Keycloak登录页面,并将令牌添加到每个额外的GET / POST /对安全服务的任何请求。我在服务和Keycloak配置中将所有ReST-Services更改为keycloak.bearer-only=true。它现在就像一个魅力。

希望这会对你有所帮助。
弗雷迪

答案 2 :(得分:0)

我们希望开发人员直接在API网关登录并直接调用服务表单。我最终通过添加一个扩展基本ZuulFilter

的过滤器来实现这一目标
public class KeycloakAuthorizationFilter extends ZuulFilter
{
private static final String AUTHORIZATION_HEADER = "Authorization";
private static final String BEARER_TOKEN_TYPE = "Bearer";
private static Logger log = LoggerFactory.getLogger(KeycloakAuthorizationFilter.class);

@Override
public Object run()
{
    log.info("Adding authenticaton header...");
    RequestContext ctx = RequestContext.getCurrentContext();

    if (ctx.getZuulRequestHeaders().containsKey(AUTHORIZATION_HEADER)) return null;

    KeycloakAuthenticationToken authentication = (KeycloakAuthenticationToken) SecurityContextHolder.getContext()
            .getAuthentication();

    if(authentication == null)
    {
        log.error("Could not load authenticaton from security context!");
    }
    else if(authentication.isAuthenticated() == false)
    {
        log.error("Not authenticated!");
    }
    else
    {
        Object principal = authentication.getPrincipal();
        if(principal != null && principal instanceof KeycloakPrincipal)
        {
            @SuppressWarnings("unchecked")
            KeycloakPrincipal<KeycloakSecurityContext> keycloakPrincipal = (KeycloakPrincipal<KeycloakSecurityContext>) authentication
                    .getPrincipal();
            log.info(String.format("Constructing Header %s for Token %s", AUTHORIZATION_HEADER, BEARER_TOKEN_TYPE));
            ctx.addZuulRequestHeader(AUTHORIZATION_HEADER, String.format("%s %s", BEARER_TOKEN_TYPE, keycloakPrincipal.getKeycloakSecurityContext().getTokenString()));
        }
    }
    return null;
}

@Override
public boolean shouldFilter()
{
    return true;
}

@Override
public int filterOrder()
{
    return 0;
}

@Override
public String filterType()
{
    return "pre";
}

}

这只是工作很棒,为您提供了更大的灵活性。

答案 3 :(得分:0)

使用版本3.3.0.Final作为启动器和适配器适用于我。当我将版本更改为3.4.3.Final时,我会得到相同的异常。

我正在运行Keycloak服务器3.4.3(独立)......

<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-spring-security-adapter</artifactId>
    <version>3.3.0.Final</version>
</dependency>

<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-spring-boot-starter</artifactId>
    <version>3.3.0.Final</version>
</dependency>

任何人都知道使用当前版本的依赖项的解决方案吗?

答案 4 :(得分:0)

在您的HttpSecurity http中,添加.anonymous().disable()以便您拥有 你的HttpSecurity就像http.anonymous().disable()

答案 5 :(得分:0)

使用Keycloak的Spring Boot class Message{ @SerializedName("SenderId") @Expose private String senderId; @SerializedName("ChatroomId") @Expose private String chatroomId; @SerializedName("MessageTxt") @Expose private String messageTxt; @SerializedName("SenderName") @Expose private String senderName; @SerializedName("updated_at") @Expose private String updatedAt; @SerializedName("created_at") @Expose private String createdAt; @SerializedName("id") @Expose private int id; public String getSenderId() { return senderId; } public void setSenderId(String senderId) { this.senderId = senderId; } public String getChatroomId() { return chatroomId; } public void setChatroomId(String chatroomId) { this.chatroomId = chatroomId; } public String getMessageTxt() { return messageTxt; } public void setMessageTxt(String messageTxt) { this.messageTxt = messageTxt; } public String getSenderName() { return senderName; } public void setSenderName(String senderName) { this.senderName = senderName; } public String getUpdatedAt() { return updatedAt; } public void setUpdatedAt(String updatedAt) { this.updatedAt = updatedAt; } public String getCreatedAt() { return createdAt; } public void setCreatedAt(String createdAt) { this.createdAt = createdAt; } public int getId() { return id; } public void setId(int id) { this.id = id; } } public interface PostChatRoomMessage { @POST("/SendToChatRoom") Call<Message[]> PostMessage(@Body Message message); } 依赖关系,如:

2

!请注意工件ID中的<dependency> <groupId>org.keycloak</groupId> <artifactId>keycloak-spring-boot-2-starter</artifactId> </dependency>

Spring Boot的父母是:

-2-

Keycloak依赖是:

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.3.RELEASE</version>
    <relativePath/>
  </parent>

答案 6 :(得分:0)

今天遇到了同样的错误。只需将keycloak http.AuthorizeRequest从allowAll()交换到authenticated()即可解决anyRequest()。

pom.xml(未编辑)

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
...
...
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.keycloak.bom</groupId>
            <artifactId>keycloak-adapter-bom</artifactId>
            <version>4.1.0.Final</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

KeycloakSecurityConfig.java(OLD)

/**
 * We require the user to be logged in for every single request
 */
@Override
protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http.authorizeRequests()
            .antMatchers("/entry/sub/*").hasRole("roleA")
            .anyRequest().permitAll();
}

KeycloakSecurityConfig.java(NEW)

/**
 * We require the user to be logged in for every single request
 */
@Override
protected void configure(HttpSecurity http) throws Exception {
    super.configure(http);
    http.authorizeRequests()
            .antMatchers("/entry/sub/*").hasRole("roleA")
            .anyRequest().authenticated();
}

答案 7 :(得分:0)

我有一个与主题启动器类似的错误,但与内部身份验证令牌有关,而不与KeyCloak有关。但是这个问题首先出现在Google上,所以我在这里回答。

我通过替换以下条目来解决了该问题:

<intercept-url pattern="^/login($|\?.*)" access="permitAll"/>

在spring security XML配置中,行如下:

<http security="none" pattern="/login" />

因此,现在Spring不会为此类请求创建匿名用户令牌。