Java Spring security loadByUsername';s的用户名字段为空
我正在开发一个RESTful web服务,并且登录正常。我想添加安全性和访问令牌,因此我添加了一个Java Spring security loadByUsername';s的用户名字段为空,java,spring,spring-security,Java,Spring,Spring Security,我正在开发一个RESTful web服务,并且登录正常。我想添加安全性和访问令牌,因此我添加了一个UserDetailsService,如下所示: @Component public class CustomLoginAuthenticationProvider implements UserDetailsService { @Autowired private BusinessUserService businessUserService; @Override
UserDetailsService
,如下所示:
@Component
public class CustomLoginAuthenticationProvider implements UserDetailsService {
@Autowired
private BusinessUserService businessUserService;
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
if(email == null || email.isEmpty() || !email.contains("@")) {
System.out.println("ERROR - THIS IS THE USERNAME:" + email);
throw new UsernameNotFoundException(email);
}
//... More below, but it doesn't matter. Exception thrown every time
}
但是,电子邮件字符串为空。我不明白为什么,因为我很难准确地理解何时调用此方法,以及发送什么值作为此方法的参数,因为这是发送给JSON的REST后端。这是我的websecurityConfigureAdapter
设置:
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Bean
public CustomLoginAuthenticationProvider customLoginAuthenticationProvider() {
return new CustomLoginAuthenticationProvider();
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/css/**", "/js/**", "/images/**", "/fonts/**",
"/videos/**", "/", "/register", "/login", "/about",
"/contact", "/test")
.permitAll()
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/"))
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.usernameParameter("email")
.passwordParameter("password")
.and()
.logout()
.logoutSuccessUrl("/")
.permitAll()
.and()
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.addFilterAfter(new CsrfTokenFilter(), CsrfFilter.class);
}
}
我指定在使用
.usernameParameter(“email”)
时应将电子邮件发送到该方法,因此我不确定它为什么不填充email参数。我在前端使用AngularJS,并使用JSON将凭据发送到后端。如果您使用JSON发送凭据,这里的错误是因为电子邮件不是http参数,包含在RequestBody中
默认设置从http参数获取凭据:
public class UsernamePasswordAuthenticationFilter extends
AbstractAuthenticationProcessingFilter {
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException(
"Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
String password = obtainPassword(request);
...
}
/**
* Enables subclasses to override the composition of the password, such as by
* including additional values and a separator.
* <p>
* This might be used for example if a postcode/zipcode was required in addition to
* the password. A delimiter such as a pipe (|) should be used to separate the
* password and extended value(s). The <code>AuthenticationDao</code> will need to
* generate the expected password in a corresponding manner.
* </p>
*
* @param request so that request attributes can be retrieved
*
* @return the password that will be presented in the <code>Authentication</code>
* request token to the <code>AuthenticationManager</code>
*/
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(passwordParameter);
}
/**
* Enables subclasses to override the composition of the username, such as by
* including additional values and a separator.
*
* @param request so that request attributes can be retrieved
*
* @return the username that will be presented in the <code>Authentication</code>
* request token to the <code>AuthenticationManager</code>
*/
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(usernameParameter);
}
您必须编写自己的筛选器,从中读取来自RequestBody的传入凭据,并在配置中将其设置在UsernamePasswordAuthenticationFilter的位置
您可以查看和如果您是用json发送凭据,这里的错误是由于电子邮件不是http参数,而是包含在RequestBody中 默认设置从http参数获取凭据:
public class UsernamePasswordAuthenticationFilter extends
AbstractAuthenticationProcessingFilter {
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException(
"Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
String password = obtainPassword(request);
...
}
/**
* Enables subclasses to override the composition of the password, such as by
* including additional values and a separator.
* <p>
* This might be used for example if a postcode/zipcode was required in addition to
* the password. A delimiter such as a pipe (|) should be used to separate the
* password and extended value(s). The <code>AuthenticationDao</code> will need to
* generate the expected password in a corresponding manner.
* </p>
*
* @param request so that request attributes can be retrieved
*
* @return the password that will be presented in the <code>Authentication</code>
* request token to the <code>AuthenticationManager</code>
*/
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(passwordParameter);
}
/**
* Enables subclasses to override the composition of the username, such as by
* including additional values and a separator.
*
* @param request so that request attributes can be retrieved
*
* @return the username that will be presented in the <code>Authentication</code>
* request token to the <code>AuthenticationManager</code>
*/
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(usernameParameter);
}
您必须编写自己的筛选器,从中读取来自RequestBody的传入凭据,并在配置中将其设置在UsernamePasswordAuthenticationFilter的位置
您可以看一看,另一个更简单的解决方案是在客户端应用程序中执行此操作,它可以与Spring Security配合使用:
public login(username: string, password: string) {
const headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
return this.http.post(
`http://www.myserver.com:8080/myApp/login`,
encodeURI(`username=${username}&password=${password}`),
{ headers }
);
}
}
这会从url中隐藏参数并将其编码为表单数据,spring security的默认实现非常喜欢这样做。另一个更简单的解决方案是在客户端应用程序中执行此操作-可以与spring security配合使用:
public login(username: string, password: string) {
const headers = new Headers();
headers.append('Content-Type', 'application/x-www-form-urlencoded');
return this.http.post(
`http://www.myserver.com:8080/myApp/login`,
encodeURI(`username=${username}&password=${password}`),
{ headers }
);
}
}
这会从url中隐藏参数并将其编码为表单数据,spring security的默认实现非常类似于此。能否将登录表单放在此处?能否将登录表单放在此处?确保将其作为参数而不是JSON数据传递。JSON数据作为参数$http({'url':'signup','method':'POST','params':user})传递的一种角度方法,请确保将它们作为参数而不是JSON数据传递。以参数$http({'url':'signup','method':'POST','params':user})的形式传递JSON数据的一种有角度的方法