问题描述
@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()
时说:
所以我想我的问题是我不了解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中找不到身份验证对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!