AuthenticationCredentialsNotFoundException:在SecurityContext中找不到身份验证对象 [英] AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext

查看:103
本文介绍了AuthenticationCredentialsNotFoundException:在SecurityContext中找不到身份验证对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在此之后在服务器上实现了登录功能发布:

@Transactional
public void login(String userId, String password) {

    LOGGER.debug("Login for " + userId);

    User user = new User(userId, password, true, true, true, true, new ArrayList<GrantedAuthority>());

    Authentication auth = new UsernamePasswordAuthenticationToken(user, password,
            new ArrayList<GrantedAuthority>());

    try {
        auth = this.authenticationProvider.authenticate(auth);
    } catch(BadCredentialsException e) {
        LOGGER.debug("Bad credentials ..");
        throw new RuntimeException(e.getMessage());
    }

    LOGGER.debug("User successfully authenticated [userId="+userId+"]");

    SecurityContext sc = new SecurityContextImpl();
    sc.setAuthentication(auth);

    SecurityContextHolder.setContext(sc);       
}

到目前为止,该方法似乎没有任何问题.但是,如果我在登录后立即执行此请求

This appears to work so far without any troubles. However, if I execute this request right after login

@PreAuthorize("hasPermission('ADMIN')")
public void test(String msg) {
    LOGGER.debug("test: " + msg);
}

结果是这里的异常:

Caused by: org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:378)
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:222)
    at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:64)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653)
    at com.mz.server.web.service.LoginService$$EnhancerBySpringCGLIB$$caf0e62d_2.test(<generated>)
    at com.mz.server.web.servlet.LoginServletImpl.test(LoginServletImpl.java:99)

读到SecurityContextHolder.setContext()时说:

将新的SecurityContext与当前执行线程相关联.

Associates a new SecurityContext with the current thread of execution.

所以我想我的问题是我不了解Spring如何召回刚登录到我的系统并且现在想继续进行身份验证请求的用户.

so I guess my problem here is that I don't understand how Spring can recall a user that just logged into my system and now wants to proceed with authenticated request.

为什么我不仅仅重定向到/login?

And why am I not just getting redirected to /login?

春季上下文:

<!-- //////////////////////////////////////////////////////////////////////////////// -->
<!-- // BEGIN Spring Security -->

<sec:http auto-config="true" use-expressions="true"/>

<bean id="httpSessionSecurityContextRepository" class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
    <property name='allowSessionCreation' value='false' />
</bean>

<bean id="securityContextPersistenceFilter" class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
    <constructor-arg ref="httpSessionSecurityContextRepository" />
</bean>

<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
    <constructor-arg>
        <list>
            <sec:filter-chain pattern="/**" filters="securityContextPersistenceFilter" />
        </list>
    </constructor-arg>
</bean>

<bean id="authenticationListener" class="com.mz.server.web.auth.CustomAuthenticationListener"/>

<bean id="authenticationProvider" class="com.mz.server.web.auth.CustomAuthenticationProvider"/>

<bean id="userDetailsService" class="com.mz.server.web.service.CustomUserDetailsService"/>

<sec:authentication-manager alias="authenticationManager">
    <sec:authentication-provider ref="authenticationProvider"/>
</sec:authentication-manager>

<sec:global-method-security 
    authentication-manager-ref="authenticationManager"
    pre-post-annotations="enabled"/>

<!-- // END Spring Security -->
<!-- //////////////////////////////////////////////////////////////////////////////// -->

web.xml

<!-- //////////////////////////////////////////////////////////////////////////////// -->
<!-- // BEGIN Filters -->

<!-- Spring Security -->

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/**</url-pattern>
</filter-mapping>

<!-- // END FILTERS -->
<!-- //////////////////////////////////////////////////////////////////////////////// -->

推荐答案

我知道您的痛苦,我真费劲地搞清楚Spring Security.真的在争论是否值得.但是您可能需要添加SecurityContextPersistenceFilter.通常,这将使用JSessionID中的HttpSession将您的凭据自动添加到SecurityContext中.我有一个自定义的身份验证处理程序,因此我的代码中有一些多余的部分不相关,但是我认为这应该可以使您指向正确的方向.

I know your pain, I had a hell of a time figuring out Spring Security. Really debating whether it was worth it. But you probably need to add the SecurityContextPersistenceFilter. This will automatically add your Credentials to the SecurityContext using the HttpSession from the JSessionID typically. I have a custom authentication handler so there is some extra parts to my code that are not relevant but I think this should probably get you pointed in the right direction.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:sec="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">


<bean id="httpSessionSecurityContextRepository"
    class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
    <property name='allowSessionCreation' value='false' />
</bean>

<bean id="securityContextPersistenceFilter"
    class="org.springframework.security.web.context.SecurityContextPersistenceFilter">
    <constructor-arg ref="httpSessionSecurityContextRepository" />
</bean>

<bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
    <constructor-arg>
        <list>
            <sec:filter-chain pattern="/rest/**"
                filters="securityContextPersistenceFilter" />
        </list>
    </constructor-arg>
</bean>

<sec:global-method-security
    authentication-manager-ref="authenticationManager"
    secured-annotations="enabled" />

这篇关于AuthenticationCredentialsNotFoundException:在SecurityContext中找不到身份验证对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆