如何使用 DaoAuthenticationProvider 以编程方式使用 Spring Security 对用户进行身份验证
Posted
技术标签:
【中文标题】如何使用 DaoAuthenticationProvider 以编程方式使用 Spring Security 对用户进行身份验证【英文标题】:How can I programmatically authenticate user with Spring Security using DaoAuthenticationProvider 【发布时间】:2013-08-03 02:08:27 【问题描述】:我想知道我在这里做错了什么来验证用户。我有一个应用程序,用户需要通过几个步骤来激活他们的帐户,然后我想绕过登录表单并将他们直接带到他们的仪表板。
这是我的自动登录功能的样子:
protected void automatedLogin(String username, String password, HttpServletRequest request)
try
// Must be called from request filtered by Spring Security, otherwise SecurityContextHolder is not updated
CustomUserDetailsService udService = new CustomUserDetailsService(userDAO, request);
UserDetails uDetails = udService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(uDetails, password);
token.setDetails(new WebAuthenticationDetails(request));
DaoAuthenticationProvider authenticator = new DaoAuthenticationProvider();
Authentication authentication = authenticator.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
catch (Exception e)
e.printStackTrace();
SecurityContextHolder.getContext().setAuthentication(null);
我必须使用 DaoAuthenticationProvider 类作为我的身份验证提供程序。我已经验证我得到了一个包含正确凭据、ID、权限角色等的 UserDetails 模型。
当它调用身份验证方法时,我在 DaoAuthenticationProvider 类中的某个地方遇到了一个空指针:
org.springframework.security.authentication.AuthenticationServiceException 在 org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:109) 在 org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:132) 在 com.bosch.actions.BaseController.doAutoLogin(BaseController.java:659) . . .引起:java.lang.NullPointerException at org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:101)
我真的不确定什么是 null,因为我没有可用的源代码。
编辑 我可以在这里找到源代码 - https://github.com/SpringSource/spring-security/blob/master/core/src/main/java/org/springframework/security/authentication/dao/DaoAuthenticationProvider.java
我能够通过在对象上显式设置 UserDetailsService 来绕过 Null 指针:
authenticator.setUserDetailsService(udService);
但是现在当我知道提供的密码正确时,我得到了错误的凭据异常,因为我已经在代码前面设置的 UserDetails 对象的调试器中看到了它。
org.springframework.security.authentication.BadCredentialsException: 凭证错误 org.springframework.security.authentication.dao.DaoAuthenticationProvider.additionalAuthenticationChecks(DaoAuthenticationProvider.java:87) 在 org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:149)
【问题讨论】:
Spring Security 是开源的,您确实有可用的源代码。您可能遇到了问题,因为 DaoAuthenticationProvider 被设计为 Spring 托管 bean。 【参考方案1】:我能够通过将 spring bean 定义中定义的所有属性拼凑在一起并以编程方式在 DaoAuthenticationProvider 对象上设置它们来使身份验证工作。回想起来,这似乎是一个愚蠢的问题,但我希望它对某人有所帮助!
更正的代码:
protected void automatedLogin(String username, String password, HttpServletRequest request)
try
// Must be called from request filtered by Spring Security, otherwise SecurityContextHolder is not updated
CustomUserDetailsService udService = new CustomUserDetailsService(userDAO, request);
CustomMd5PasswordEncoder passEncoder = new CustomMd5PasswordEncoder();
ReflectionSaltSource saltSource = new ReflectionSaltSource();
saltSource.setUserPropertyToUse("salt");
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
token.setDetails(new WebAuthenticationDetails(request));
DaoAuthenticationProvider authenticator = new DaoAuthenticationProvider();
authenticator.setUserDetailsService(udService);
authenticator.setPasswordEncoder(passEncoder);
authenticator.setSaltSource(saltSource);
Authentication authentication = authenticator.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
catch (Exception e)
e.printStackTrace();
SecurityContextHolder.getContext().setAuthentication(null);
【讨论】:
很高兴您找到了解决方法,但老实说,这并不是 Spring Security 的初衷。你自己做了很多工作,你不应该这样做。 这不是应用中Spring Security的正常使用。这是一个一次性实例,我需要让用户登录,而不需要他们在表单中提供凭据。每隔一次,他们将通过表单登录,spring security bean 将完成这项工作。解释了这一点后,如果您是对答案投反对票的人,我希望您改变主意,因为我认为这不公平地损害了我在 *** 上的声誉。 请放心,我的朋友,我没有对你投反对票。我不认为答案不正确,我只是在暗示 Spring Security 不应该以这种方式使用。 P.S.否决投票你也会降低我在 SO 上的声誉...... :) 此外,以这种方式以编程方式进行身份验证也可以在功能测试套件中使用,这就是我来到这里的原因。不要假设上下文。以上是关于如何使用 DaoAuthenticationProvider 以编程方式使用 Spring Security 对用户进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章
如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]
如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?