具有 Spring Security 和 Java 配置的自定义身份验证管理器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31826233/
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
Custom Authentication Manager with Spring Security and Java Configuration
提问by Jeff I
I am using Spring Security with SpringMVC to create a web application (I will refer to this as the WebApp for clarity) that speaks to an existing application (I will refer to this as BackendApp).
我正在使用 Spring Security 和 SpringMVC 创建一个与现有应用程序(我将其称为 BackendApp)对话的 Web 应用程序(为了清楚起见,我将其称为 WebApp)。
I want to delegate authentication responsibilities to the BackendApp (so that I don't need to synchronise the two applications).
我想将身份验证职责委托给 BackendApp(这样我就不需要同步两个应用程序)。
To implement this, I would like the WebApp (running spring security) to communicate to the BackendApp via REST with the username and password provided by the user in a form and authenticate based on whether the BackendApp's response is 200 OK or 401 Unauthorised.
为了实现这一点,我希望 WebApp(运行 spring security)使用用户在表单中提供的用户名和密码通过 REST 与 BackendApp 通信,并根据 BackendApp 的响应是 200 OK 还是 401 Unauthorised 进行身份验证。
I understand I will need to write a custom Authentication Manager to do this however I am very new to spring and can't find any information on how to implement it.
我知道我需要编写一个自定义身份验证管理器来执行此操作,但是我对 spring 很陌生,无法找到有关如何实现它的任何信息。
I believe I will need to do something like this:
我相信我需要做这样的事情:
public class CustomAuthenticationManager implements AuthenticationManager{
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String pw = authentication.getCredentials().toString();
// Code to make rest call here and check for OK or Unauthorised.
// What do I return?
}
}
Do I set authentication.setAuthenticated(true) if successful and false if otherwise and thats it?
如果成功,我是否设置 authentication.setAuthenticated(true) ,否则设置为 false ,仅此而已?
Once this is written, how do I configure spring security to use this authentication manager using a java configuration file?
写完后,如何使用 java 配置文件配置 spring security 以使用此身份验证管理器?
Thanks in advance for any assistance.
在此先感谢您的帮助。
采纳答案by Halko Karr-Sajtarevic
Take a look at my sample below. You have to return an UsernamePasswordAuthenticationToken. It contains the principal and the GrantedAuthorities. Hope I could help :)
看看我下面的示例。您必须返回一个 UsernamePasswordAuthenticationToken。它包含主体和 GrantedAuthorities。希望我能帮上忙:)
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getPrincipal() + "";
String password = authentication.getCredentials() + "";
User user = userRepo.findOne(username);
if (user == null) {
throw new BadCredentialsException("1000");
}
if (!encoder.matches(password, user.getPassword())) {
throw new BadCredentialsException("1000");
}
if (user.isDisabled()) {
throw new DisabledException("1001");
}
List<Right> userRights = rightRepo.getUserRights(username);
return new UsernamePasswordAuthenticationToken(username, null, userRights.stream().map(x -> new SimpleGrantedAuthority(x.getName())).collect(Collectors.toList()));
}
PS: userRepo and rightRepo are Spring-Data-JPA Repositories which access my custom User-DB
PS:userRepo 和 rightRepo 是 Spring-Data-JPA 存储库,它们访问我的自定义 User-DB
SpringSecurity JavaConfig:
SpringSecurity JavaConfig:
@Configuration
@EnableWebMvcSecurity
public class MySecurityConfiguration extends WebSecurityConfigurerAdapter {
public MySecurityConfiguration() {
super(false);
}
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return new ProviderManager(Arrays.asList((AuthenticationProvider) new AuthProvider()));
}
}
回答by Ricardo Vila
First you must configure Spring security to use your custom AuthenticationProvider. So, in your spring-security.xml (or equivalent config file) you must define wich class is implementing this feature. For example:
首先,您必须配置 Spring security 以使用您的自定义 AuthenticationProvider。因此,在您的 spring-security.xml(或等效配置文件)中,您必须定义实现此功能的类。例如:
<authentication-manager alias="authenticationManager">
<authentication-provider ref="myAuthenticationProvider" />
</authentication-manager>
<!-- Bean implementing AuthenticationProvider of Spring Security -->
<beans:bean id="myAuthenticationProvider" class="com.teimas.MyAutenticationProvider">
</beans:bean>
Secondly you must implement AuthenticationProvider as in your example. Specially the method authenticate(Authentication authentication) in which your rest call must be. For example:
其次,您必须像示例中一样实现 AuthenticationProvider 。特别是您的休息调用必须使用的方法身份验证(身份验证)。例如:
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
User user = null;
try {
//use a rest service to find the user.
//Spring security provides user login name in authentication.getPrincipal()
user = userRestService.loadUserByUsername(authentication.getPrincipal().toString());
} catch (Exception e) {
log.error("Error loading user, not found: " + e.getMessage(), e);
}
if (user == null) {
throw new UsernameNotFoundException(String.format("Invalid credentials", authentication.getPrincipal()));
} else if (!user.isEnabled()) {
throw new UsernameNotFoundException(String.format("Not found enabled user for username ", user.getUsername()));
}
//check user password stored in authentication.getCredentials() against stored password hash
if (StringUtils.isBlank(authentication.getCredentials().toString())
|| !passwordEncoder.isPasswordValid(user.getPasswordHash(), authentication.getCredentials().toString()) {
throw new BadCredentialsException("Invalid credentials");
}
//doLogin makes whatever is necesary when login is made (put info in session, load other data etc..)
return doLogin(user);
}
回答by mel3kings
In its most simplest:
最简单的:
@Override
public Authentication authenticate(Authentication auth) throws AuthenticationException {
String username = auth.getName();
String password = auth.getCredentials().toString();
// to add more logic
List<GrantedAuthority> grantedAuths = new ArrayList<>();
grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
return new UsernamePasswordAuthenticationToken(username, password, grantedAuths);
}
回答by Andrew Gans
My solution is almost the same as the first answer:
我的解决方案与第一个答案几乎相同:
1) You need a class which implements the Authentication Provider
1)您需要一个实现身份验证提供程序的类
@Service
@Configurable
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// Your code of custom Authentication
}
}
2) Opposite to the first answer you don'tneed to have following code in your WebSecurityConfiguration if you have only this custom provider.
你2)相对于第一答案并不需要具备以下在WebSecurityConfiguration代码,如果你只有这个定义提供。
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return new ProviderManager(Arrays.asList((AuthenticationProvider) new AuthProvider()));
}
The issue is that Spring looks for available providers and use the default if nothing else is found. But as you have the implementation of the AuthenticationProvider - your implementation will be used.
问题是 Spring 会寻找可用的提供者,如果找不到其他提供者,则使用默认值。但是由于您拥有 AuthenticationProvider 的实现 - 将使用您的实现。