带有 Java 配置的 Spring Boot 自定义身份验证提供程序不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36721212/
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 Boot Custom Authentication Provider with Java Configuration not working
提问by H?vard Bakke
I am trying to setup a REST based web application, where the frontend is using Reactjs and the backend is using Spring Boot. I am also trying to setup a custom authentication provider, and this is where my problems start. When trying to test the login API call, the CustomAuthenticationProvider is never called, and instead the default DaoAuthenticationProvider is used. This causes the login to report "Bad credentials".
我正在尝试设置一个基于 REST 的 Web 应用程序,其中前端使用 Reactjs,后端使用 Spring Boot。我也在尝试设置自定义身份验证提供程序,这就是我的问题开始的地方。尝试测试登录 API 调用时,从不调用 CustomAuthenticationProvider,而是使用默认的 DaoAuthenticationProvider。这会导致登录报告“凭据错误”。
I have upload a small sample application to github: spring-boot-auth-demo
我已将一个小示例应用程序上传到 github:spring-boot-auth-demo
To test the login API I use the following curl:
为了测试登录 API,我使用以下 curl:
curl -H "Content-Type: application/json" -X POST -d '{"username":"admin","password":"admin"}' http://localhost:8080/api/users/login
The CustomAuthenticationProvider does a simple username/password check and returns an UsernamePasswordAuthenicationToken object.
CustomAuthenticationProvider 执行简单的用户名/密码检查并返回 UsernamePasswordAuthenicationToken 对象。
package no.bluebit.demo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
private static final Logger logger = LoggerFactory.getLogger(CustomAuthenticationProvider.class);
public CustomAuthenticationProvider() {
logger.info("*** CustomAuthenticationProvider created");
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
if(authentication.getName().equals("admin") && authentication.getCredentials().equals("admin")) {
List<GrantedAuthority> grantedAuths = new ArrayList<>();
grantedAuths.add(new SimpleGrantedAuthority("ROLE_USER"));
grantedAuths.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
return new UsernamePasswordAuthenticationToken(authentication.getName(), authentication.getCredentials(), grantedAuths);
} else {
return null;
}
}
@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
}
The CustomAuthenticationProvider is wired up using the SecurityConfiguration class. When stepping through the code, I can see that the CustomAuthenicationProvider is not in the list of providers used to authenticate the incoming request.
CustomAuthenticationProvider 使用 SecurityConfiguration 类进行连接。在逐步执行代码时,我可以看到 CustomAuthenicationProvider 不在用于对传入请求进行身份验证的提供程序列表中。
package no.bluebit.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(this.customAuthenticationProvider);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/users/login").permitAll() // Permit access for all to login REST service
.antMatchers("/").permitAll() // Neccessary to permit access to default document
.anyRequest().authenticated().and() // All other requests require authentication
.httpBasic().and()
.logout().and()
.csrf().disable();
}
}
Why is this not working?
为什么这不起作用?
回答by Catalin Stan
Look at the AuthenticationProvider class (respectively it's java doc)
查看 AuthenticationProvider 类(分别是java doc)
The method authenticate expects to :
方法身份验证期望:
* Performs authentication with the same contract as
* {@link org.springframework.security.authentication.AuthenticationManager#authenticate(Authentication)}
* @return a fully authenticated object including credentials. May return
* <code>null</code> if the <code>AuthenticationProvider</code> is unable to support
* authentication of the passed <code>Authentication</code> object. In such a case,
* the next <code>AuthenticationProvider</code> that supports the presented
* <code>Authentication</code> class will be tried.
If you return null, then the next AuthenticationProvider will be called, which is the defaut one.
如果返回 null,则将调用下一个 AuthenticationProvider,这是默认的。
I am not sure this is the problem, but this might be something. Try to throw BadCredentialsException, as the AuthenticationManager class tells you to do :
我不确定这是问题所在,但这可能是问题所在。尝试抛出 BadCredentialsException,因为 AuthenticationManager 类告诉你这样做:
* <li>A {@link BadCredentialsException} must be thrown if incorrect credentials are
* presented. Whilst the above exceptions are optional, an
* <code>AuthenticationManager</code> must <B>always</B> test credentials.</li>
回答by Dexter
You have to set the credentials in some other way. Try to see a working example of Username Password token. But your "authenticate" function needs to be the one that sets the credentials.
您必须以其他方式设置凭据。尝试查看用户名密码令牌的工作示例。但是您的“身份验证”功能必须是设置凭据的功能。
回答by Nico
Try to add on header http this thinks:
尝试添加头 http 这认为:
Example:
例子:
const headers = new HttpHeaders();
headers.set('Access-Control-Allow-Origin', '*');
headers.set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, DELETE, PUT');
headers.set('Access-Control-Allow-Headers', 'Authorization, Content-Type, Accept, x-
requested-with, Cache-Control');
headers.set('Content-Type', 'application/json');
this.http.post('http://localhost:8081/loginAngular',
JSON.stringify({user: 'sdasd', password: 'dasdasd', estado: 'dasdasd', idUsuario: 1, resultado: 'asdasd'}) ,
{headers: new HttpHeaders().set('Content-Type', 'application/json')}).subscribe(data => {
console.log(' Data: ' + data);
});
I made this app with spring security and angular! Front: https://github.com/nicobassart/angularforHidraBack: https://github.com/nicobassart/hidra_server
我用弹簧安全和角度制作了这个应用程序!正面:https: //github.com/nicobassart/angularforHidra背面:https: //github.com/nicobassart/hidra_server