如何解决带有Java配置的Spring启动自定义身份验证提供程序无法工作?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (79)

我正在尝试设置基于REST的Web应用程序,其中前端使用Reactjs,后端使用Spring Boot。我也在尝试设置自定义身份验证提供程序,这就是我的问题开始的地方。尝试测试登录API调用时,从不调用CustomAuthenticationProvider,而是使用默认的DaoAuthenticationProvider。这会导致登录报告“错误凭据”。

我已经将一个小样本应用程序上传到github:spring-boot-auth-demo

要测试登录API,我使用以下curl:

curl -H "Content-Type: application/json" -X POST -d '{"username":"admin","password":"admin"}' http://localhost:8080/api/users/login

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);
}

}

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();
    }
}

为什么这不起作用?

提问于
用户回答回答于

查看AuthenticationProvider类(分别是它的java doc)

验证方法期望:

 * 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.

如果返回null,则将调用下一个AuthenticationProvider,这是默认的。

我不确定这是什么问题,但这可能是件事。尝试抛出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>
用户回答回答于

尝试添加标题http这认为:

例:

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);

});

我用弹簧安全和角度制作了这个应用程序!前面:https//github.com/nicobassart/angularforHidra返回:https//github.com/nicobassart/hidra_server

扫码关注云+社区

领取腾讯云代金券