简体   繁体   English

带有 Java 配置的 Spring Boot 自定义身份验证提供程序不起作用

[英]Spring Boot Custom Authentication Provider with Java Configuration not working

I am trying to setup a REST based web application, where the frontend is using Reactjs and the backend is using Spring Boot.我正在尝试设置一个基于 REST 的 Web 应用程序,其中前端使用 Reactjs,后端使用 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.尝试测试登录 API 调用时,从不调用 CustomAuthenticationProvider,而是使用默认的 DaoAuthenticationProvider。 This causes the login to report "Bad credentials".这会导致登录报告“凭据错误”。

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. CustomAuthenticationProvider 使用 SecurityConfiguration 类进行连接。 When stepping through the code, I can see that the CustomAuthenicationProvider is not in the list of providers used to authenticate the incoming request.在逐步执行代码时,我可以看到 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?为什么这不起作用?

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/angularforHidra Back: https://github.com/nicobassart/hidra_server正面: https : //github.com/nicobassart/angularforHidra背面: https : //github.com/nicobassart/hidra_server

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>

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.但是您的“身份验证”功能必须是设置凭据的功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM