Spring Security没有授权

时间:2018-02-03 13:16:32

标签: spring spring-security

我一直在关注指南,但我无法让Spring Security工作。 它看起来像是在验证但不是授权或反之,或者没有重定向到登录成功页面。也许这是一个愚蠢的错误,但我看不到它。

我的春季安全配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private Environment env;

    @Autowired
    private UserSecurityService userSecurityService;

    private static final String[] PUBLIC_MATCHERS = { 
        "/webjars/**", 
        "/css/**", 
        "/js/**", 
        "/images/**", 
        "/",
        "/about/**", 
        "/contact/**", 
        "/error/**/*",
        "/h2-console/**"
    };

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        List<String> activeProfiles = Arrays.asList(env.getActiveProfiles());
        // Required by h2 console to work
        if(activeProfiles.contains("dev")) {
            http.csrf().disable();
            http.headers().frameOptions().disable();
        }
        http
            .authorizeRequests()
            .antMatchers(PUBLIC_MATCHERS).permitAll()
            .anyRequest().authenticated()
            .and()
            .formLogin().loginPage("/login").defaultSuccessUrl("/payload")
            .failureUrl("/login?error").permitAll()
            .and()
            .logout().permitAll();
    }

    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userSecurityService);   
    }    
}

application-dev.properties

spring.datasource.url=jdbc:h2:mem:testdb;MODE=MySQL;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=
hibernate.dialect=org.hibernate.dialect.H2Dialect

日志:

  

DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - 以前经过身份验证:org.springframework.security.authentication.AnonymousAuthenticationToken@2dafa81d:Principal:anonymousUser;证书:[保护];认证:真实;详细信息:org.springframework.security.web.authentication.WebAuthenticationDetails@2cd90:RemoteIpAddress:0:0:0:0:0:0:0:1; SessionId:0D60174BBA25377F65443D95DB72F713;授权机构:ROLE_ANONYMOUS

     

DEBUG o.s.s.access.vote.AffirmativeBased - Voter:org.springframework.security.web.access.expression.WebExpressionVoter@7a27baf6,返回:1

     

DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - 授权成功

     

DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager没有更改身份验证对象

     

DEBUG o.s.security.web.FilterChainProxy - /js/scripts.js到达了额外的过滤器链的末尾;继续原始链

     

DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext为空或内容为匿名 - 上下文不会存储在HttpSession中。

     

DEBUG o.s.s.w.a.ExceptionTranslationFilter - 正常处理链

     

DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder现已清除,请求处理完成

     

DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext为空或内容为匿名 - 上下文不会存储在HttpSession中。

     

DEBUG o.s.s.w.a.ExceptionTranslationFilter - 正常处理链

     

DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder现已清除,请求处理完成

1 个答案:

答案 0 :(得分:4)

在身份验证期间,应用程序会抛出以下错误:

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

抛出此异常,因为提供的(纯文本)密码缺少密码编码器{id} - 前缀。 Spring Security 5现在使用以下格式存储密码(以前版本的spring security不是这种情况):

{id}encodedPassword

这意味着对于纯文本密码,{noop} id告诉spring使用NoOpPasswordEncoder(基本上将密码作为纯文本处理)来匹配密码。

但是,非常不鼓励存储纯文本密码(尽管它可能对自动化测试很有用)。

使用密码编码器

强烈建议您使用BCryptPasswordEncoderPbkdf2PasswordEncoderSCryptPasswordEncoder

<强> BCryptPasswordEncoder

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
class Config {

    @Bean
    public PasswordEncoder passwordEncoder() {
        // Create an encoder with strength 31
        // values from 4 .. 31 are valid; the higher the value, the more work has to be done to calculate the hash
        return new BCryptPasswordEncoder(12);
    }
}

安全配置

@Configuration
class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    PasswordEncoder passwordEncoder;

    ...

    @Autowired
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userSecurityService)
            .passwordEncoder(passwordEncoder);
    }
}

编码密码

@Service
class UserService implements UserDetailsService {
    private UserRepository userRepository;
    private PasswordEncoder passwordEncoder;

    UserService(UserRepository userRepository, PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
    }    

    User createUser(String username, String password) {
        // encrypt the plain-text password
        String encodedPassword = passwordEncoder.encode(password);
        User user = new User(username, encodedPassword));
        //...
        return userRepository.save(user);
    }
}

支持多个编码器

要支持多个编码器,可能需要查看DelegatingPasswordEncoderPasswordEncoderFactories

有关详细信息,请查看https://spring.io/blog/2017/11/01/spring-security-5-0-0-rc1-released#password-storage-format