java Spring Security 自定义身份验证 - AuthenticationProvider 与 UserDetailsService
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31630818/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring Security Custom Authentication - AuthenticationProvider vs UserDetailsService
提问by Evgeni Dimitrov
As far as I can understand when you want custom authentication in Spring Security you can either implement a custom AuthenticationProvider
or custom UserDetailsService
.
据我所知,当您想要在 Spring Security 中进行自定义身份验证时,您可以实现自定义AuthenticationProvider
或自定义UserDetailsService
.
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
//.authenticationProvider(authProvider) // option 1
.userDetailsService(userDetailsService); // option 2
}
In the AuthenticationProvider you can check the username and password and return Authentication
with your custom object in it.
在 AuthenticationProvider 中,您可以检查用户名和密码,并在其中返回Authentication
自定义对象。
public Authentication authenticate(Authentication authentication){
if (checkUsernameAndPassword(authentication)) {
CustomUserDetails userDetails = new CustomUserDetails();
//add whatever you want to the custom user details object
return new UsernamePasswordAuthenticationToken(userDetails, password, grantedAuths);
} else {
throw new BadCredentialsException("Unable to auth against third party systems");
}
}
In the UserDetailsService
you get only the username and when you return the custom UserDeatails, the framework performs a check on the password.
在UserDetailsService
您只获得用户名时,当您返回自定义 UserDeatails 时,框架会检查密码。
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
CustomUserDetails user = new CustomUserDetails();
//add whatever you want to the custom user details object
return user;
}
Looks like both can produce similar results. So the question is what is the difference? When to user one vs the other?
看起来两者都可以产生相似的结果。所以问题是有什么区别?何时使用一个与另一个?
采纳答案by Hossein
The answer is inside your question. when you are using a different authentication system, and the password is not provided in your own database/data model, you have to use the AuthenticationProvider. for example, I've worked in a project that the customer had a centralized authentication system (CAS), so my system had no idea about the password, I had to implement the AuthenticationProvider and send the given password to the CAS, and act according to its answer.
答案就在您的问题中。当您使用不同的身份验证系统,并且您自己的数据库/数据模型中未提供密码时,您必须使用 AuthenticationProvider。例如,我在一个项目中工作,客户有一个集中式身份验证系统(CAS),所以我的系统不知道密码,我必须实现 AuthenticationProvider 并将给定的密码发送给 CAS,然后按照到它的答案。
But in another system, I was storing the password in my database, so all I had to do was implementing the UserDetailsService and check if the user exists in my database or not, spring-security had to do the rest.
但是在另一个系统中,我将密码存储在我的数据库中,所以我所要做的就是实现 UserDetailsService 并检查用户是否存在于我的数据库中,剩下的事情就交给 spring-security 了。
回答by Gautam Tadigoppula
From spring security documention, https://docs.spring.io/spring-security/site/docs/5.0.0.RC1/reference/htmlsingle/#overall-architecture
来自 spring 安全文档, https://docs.spring.io/spring-security/site/docs/5.0.0.RC1/reference/htmlsingle/#overall-architecture
There is often some confusion about UserDetailsService. It is purely a DAO for user data and performs no other function other than to supply that data to other components within the framework. In particular, it does not authenticate the user, which is done by the AuthenticationManager. In many cases it makes more sense to implement AuthenticationProvider directly if you require a custom authentication process.
关于 UserDetailsService 经常有一些混淆。它纯粹是用于用户数据的 DAO,除了向框架内的其他组件提供该数据外,不执行其他任何功能。特别是,它不验证用户,这是由 AuthenticationManager 完成的。在许多情况下,如果您需要自定义身份验证过程,直接实现 AuthenticationProvider 更有意义。
AuthenticationProvider and UserDetailsService have different purpose.
AuthenticationProvider 和 UserDetailsService 有不同的用途。
AuthenticationProvider authenticates(compares) the user(request) provided username and password against system User(This can be any system like DB which maintains list of registered users)
AuthenticationProvider 验证(比较)用户(请求)提供的用户名和密码与系统用户(这可以是任何系统,如维护注册用户列表的 DB)
It is the responsiblity of UserDetailsService Implementation to get the System User Details that match with user provided Username. Here it just gets the users that have same username and does not tell the application whether authentication is successful or failed.
获取与用户提供的用户名匹配的系统用户详细信息是 UserDetailsService 实现的责任。这里它只获取具有相同用户名的用户,并没有告诉应用程序身份验证是成功还是失败。
Example : Spring provides the following as a default setup to authenticate a user details against database
示例:Spring 提供以下默认设置来针对数据库验证用户详细信息
- AuthenticationProvider - DaoAuthenticationProvider which extends AbstractUserDetailsAuthenticationProvider that calls the authenticate method by passing on username, Authentication object
- UserDetailsService - JdbcDaoImpl
- Flow of authentication
- AuthenticationProvider - DaoAuthenticationProvider 扩展了 AbstractUserDetailsAuthenticationProvider,它通过传递用户名、Authentication 对象来调用身份验证方法
- UserDetailsService - JdbcDaoImpl
- 认证流程
- DaoAuthenticationProvider responsibility is to authenticate the username and password obtained from request with Database user.
- To get the corresponding Database User, it asks UserDetailsService Implementataion JdbcDaoImpl to get a UserDetail object from database with name same as request username.Here JdbcDaoImpl just fetches the UserDetails object from system.It will either send back the user found in DB or send an exception that user is not found.
- If user details are found in DB, DaoAuthenticationProvider then proceeds with checking on request user password with DB found user password else fails the authentication.
- DaoAuthenticationProvider will respond whether the user is authenticated or not based on JdbcDaoImpl response.
- DaoAuthenticationProvider 的职责是向数据库用户验证从请求中获取的用户名和密码。
- 为了获取对应的数据库用户,它要求 UserDetailsService Implementationataion JdbcDaoImpl 从数据库中获取一个名称与请求用户名相同的 UserDetail 对象。这里 JdbcDaoImpl 只是从系统中获取 UserDetails 对象。它要么将在 DB 中找到的用户发回,要么发送异常找不到该用户。
- 如果在 DB 中找到用户详细信息,DaoAuthenticationProvider 然后继续检查请求用户密码并使用 DB 找到的用户密码,否则身份验证失败。
- DaoAuthenticationProvider 将根据 JdbcDaoImpl 响应来响应用户是否通过身份验证。
Have a look here to understand it better:
看看这里以更好地理解它:
AuthenticationProvider - DaoAuthenticationProviderextends AbstractUserDetailsAuthenticationProvider
AuthenticationProvider - DaoAuthenticationProvider扩展AbstractUserDetailsAuthenticationProvider
UserDetailsService - JdbcDaoImpl
UserDetailsService - JdbcDaoImpl
UserDetails - User
回答by Denis Wang
Those two are related but is intentionally separated by Spring Security. If the enterprise has multiple systems, UserDetailsService will provide the specific user's information held by your particular system even though the authentication MIGHT be carried out by totally another system. In a simple system, they can be combined. For example, a database call will verify the username/password and retrieve all that user's email, ID and etc.
这两者是相关的,但被 Spring Security 有意分开。如果企业有多个系统,UserDetailsService 将提供您的特定系统持有的特定用户信息,即使认证可能完全由另一个系统执行。在一个简单的系统中,它们可以组合在一起。例如,数据库调用将验证用户名/密码并检索该用户的所有电子邮件、ID 等。
According to Spring Security Reference: http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#getting-started
根据 Spring 安全参考:http: //docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#getting-started
There is often some confusion about UserDetailsService. It is purely a DAO for user data and performs no other function other than to supply that data to other components within the framework. In particular, it does not authenticate the user, which is done by the AuthenticationManager. In many cases it makes more sense to implement AuthenticationProvider directly if you require a custom authentication process.
关于 UserDetailsService 经常有一些混淆。它纯粹是用于用户数据的 DAO,除了向框架内的其他组件提供该数据外,不执行其他任何功能。特别是,它不验证用户,这是由 AuthenticationManager 完成的。在许多情况下,如果您需要自定义身份验证过程,直接实现 AuthenticationProvider 更有意义。