在Spring Security中结合用户名/密码登录与证书 [英] Combine username/password login with certificate in Spring Security

查看:700
本文介绍了在Spring Security中结合用户名/密码登录与证书的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Spring MVC开发一个webapp,我使用Spring Security并且已经编写了用户名/密码登录的代码。现在我必须编写代码以允许用户使用证书登录...我从一个cardreader读取数据并处理它,然后我创建一个UserDetails对象,然后UsernamePasswordAuthenticationToken,并加载到Spring安全上下文如下: / p>

I'm developing a webapp with Spring MVC, I use Spring Security and have already written the code for username/password login and it works. Now I have to write the code to allow users to log in with a certificate... I read data from a cardreader and process it and then I create a UserDetails object, then a UsernamePasswordAuthenticationToken and load it to Spring security context like this:

UserDetails userDetails = myUserDetailsService.loadUserByUsername(usuario.getCodUsuario());

Authentication auth = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

SecurityContextHolder.getContext().setAuthentication(auth);

然后我将用户重定向到一个视图,他可以看到他应该的菜单部分他的凭证,但当他点击一个选项,突然Spring Security抛出一个未认证异常...

Then I redirect the user to a view, and he can see the menu parts that he's supposed to according to his credentials, but when he clicks an option, suddenly Spring Security throws a "not authenticated" exception...

编辑:这是我的Spring Security配置:

here's my Spring Security config:

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

<http pattern="/resources/**" security="none" />
<http pattern="/login" security="none" />
<http pattern="/firma" security="none" />

<http auto-config="true" use-expressions="true">
<intercept-url pattern="/**" access="isAuthenticated()" />
<form-login login-page="/login" default-target-url="/home" login-processing-url="/j_spring_security_check" always-use-default-target="true" authentication-failure-url="/login?loginError"/>
<logout logout-url="/logout"/>
</http>

<beans:bean id="UserPasswordAuthenticationProvider" class="es.mywebapp.common.security.UserPasswordAuthenticationProvider"/>

<authentication-manager>
<authentication-provider ref="UserPasswordAuthenticationProvider"/>
</authentication-manager>

</beans:beans>

例外情况如下:

DEBUG 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:83)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:206)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:115)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:152)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:662)


推荐答案

这里发生的是您将认证令牌分配给SecurityContextHolder。但似乎SecurityContextHolder没有附加到任何会话。所以当ThreadLocal关闭时SecurityContextHolder丢失。 (这是一个假设,我不能验证与可用的信息。你需要更新问题或检查自己
你必须附加 SecurityContext 到Session:

What is happening here is that you assign the authentication token to the SecurityContextHolder. But it seems like the SecurityContextHolder is not attached to any Session. So when the ThreadLocal closes the SecurityContextHolder is lost. (This is an assumption which i can not verify with the information available. You need to update the question or check for yourself You have to attach the SecurityContext to the Session:

SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(authentication);

// Create a new session and add the security context.
HttpSession session = request.getSession(true);
session.setAttribute("SPRING_SECURITY_CONTEXT", securityContext);

如果在设置中创建 SecurityContextHolder Web上下文/会话Spring应该通过 SecurityContextPersistenceFilter 处理附加到会话并从会话中检索它。因此,如果是这种情况,您不应该使用第一个解决方案,配置 FilterChain

If the SecurityContextHolder is created in a setting where it is part of the web context/ session Spring should handle attaching it to and retrieving it from the session via the SecurityContextPersistenceFilter. So if this is the case you should not employ the first solution but rather check the configuration of your FilterChain.

链接详解将SecurityContextHolder附加到会话如何在Spring中手动设置经过身份验证的用户Security / SpringMVC

根据网络应用程序,详细说明 SecurityContextHolder: http://static.springsource.org/spring- security / site / docs / 3.0.x / reference / technical-overview.html

这篇关于在Spring Security中结合用户名/密码登录与证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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