用户名密码配置的三种方式 推荐第三种
- 配置文件
spring:
security:
user:
name: root
password: root
- 配置类
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 密码加密器
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
auth.inMemoryAuthentication()
.passwordEncoder(encoder) // 告诉其使用的加密器是什么,也可以不告诉.而是将这个对象存储到Spring容器中也可以
.withUser("root")
.password(encoder.encode("root"))
.roles("user"); // 这个角色是必须有的,现在不知道是为什么
}
}
// 注入Bean的写法
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private BCryptPasswordEncoder encoder;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("root")
.password(encoder.encode("root"))
.roles("user");
}
@Bean
public BCryptPasswordEncoder getEncoder(){
return new BCryptPasswordEncoder();
}
}
- 自定义编写实现类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@Configuration
public class SecurityConfigThree extends WebSecurityConfigurerAdapter {
@Autowired
private BCryptPasswordEncoder encoder;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 这一步的操作应该是要抽取出来未一个实现类的.用户 权限 在从数据库中进行查询
auth.userDetailsService(new UserDetailsService() {
@Override // 这个username就是前端提交过来的
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 采用这种方式进行配置.security将用户名的验证权力交给了我们,其只对密码进行校验
// new ArrayList<>()
if (username!=null && username.equalsIgnoreCase("root"))
return new User(
"root",
encoder.encode("root"), //这里虽然使用到了加密的 但实际应用中是用不到的
Collections.singletonList(new SimpleGrantedAuthority("user"))
);
// UsernameNotFoundException 这个异常security会进行捕获,并给前端反馈其默认的错误提示
// 其他异常才可以将我们想要的错误提示反馈给前端.
throw new RuntimeException("用户名不存在");
}
});
}
@Bean
public BCryptPasswordEncoder getEncoder() {
return new BCryptPasswordEncoder();
}
}
补充说明
解释.passwordEncoder(encoder)为什么可以不用执行,而是注入bean就可以了
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.LazyPasswordEncoder#getPasswordEncoder
if (this.passwordEncoder != null) {
return this.passwordEncoder;
}
PasswordEncoder passwordEncoder = getBeanOrNull(PasswordEncoder.class);
不注入的Bean的问题:参考
> https://www.cnblogs.com/zouhong/p/11946037.html
当没有指定解密器的时候会使用默认的 org.springframework.security.crypto.password.DelegatingPasswordEncoder
当然不推荐让他默认生成. 默认生成会生成十几个.最后在通过key取匹配解密器 DelegatingPasswordEncoder.extractId 获取key
key的来源:
new User(
"root",
"{bcrypt}"+new BCryptPasswordEncoder().encode("root"),
Collections.singletonList(new SimpleGrantedAuthority("user"))
);
key是在创建用户的时候指定的.还不如直接注入Bean