密码加密
Spring Security提供了多种密码加密方案,官方推荐使用BCryptPasswordEncoder,BCryptPasswordEncoder使用BCrypt强哈希函数,开发者在使用时可以选择提供strength和SecureRandom实例。strength越大,密钥的迭代次数越多,密钥迭代次数为2^strength。strength取值在4~31之间,默认为10.
在Spring boot中配置密码加密非常容易,只需要修改上文配置的PasswordEnoder这个Bean的实现即可:
@Bean
PasswordEncoder passwordEncoder(){
//参数10就是strength,即密钥的迭代次数(默认为10)
return new BCryptPasswordEncoder(10);
}
同时,配置内存用户的密码也不再是123了,代码如下:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin")
.password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqi1Xzbz50dceRsga.WYiq")
.roles("ADMIN", "USER")
.and()
.withUser("sang")
.password("$2a$10$eUHbAOMq4bpxTvOVz33LIehLe3fu6NwqC9tdOcxJXEHyz4simqXTC")
.roles("USER");
}
这里的密码就是使用BCryptPasswordEncoder加密后的密码,因为BCryptPasswordEncoder每次加密的结果都不一样,所以几乎匹配不上,上述代码只是说明原理而已。
一般情况下,用户信息是存储在数据库中的,因此需要在用户注册时对密码进行加密处理,代码如下:
@Service
public class RegService {
public int reg(String username, String password){
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(10);
String encodePassword = encoder.encode(password);
return saveToDb(username, password);
}
}
用户将密码从前端传来之后,通过调用BCryptPasswordEncoder实例中的encode方法对密码进行加密处理,加密完成后将密文存入数据库。
方法安全
除了基于URL的认证与授权,开发者也可以通过注解来灵活地配置方法安全,要使用相关注解,首先要通过@EnableGlobalMethodSecurity注解开启基于注解的安全配置:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig {
}
-
prePostEnabled=true会解锁@PreAuthorize和@PostAuthorize两个注解
- @PreAuthorize注解会在方法执行前进行验证
- @PostAuthorize注解在方法执行后进行验证
-
securedEnabled=true会解锁@Secured注解
创建一个MethodService进行测试:
@Service
public class MethodService {
//表示该访问该方法需要ADMIN角色,注意:需要加前缀ROLE_
@Secured("ROLE_ADMIN")
public String admin(){
return "hello admin";
}
//表示访问该方法需要ADMIN和DBA角色
@PreAuthorize("hasRole('ADMIN') and hasRole('DBA')")
public String adminAndDba(){
return "hello admin and dba";
}
//表示访问该方法需要ADMIN、DBA或者USER角色
@PreAuthorize("hasAnyRole('ADMIN', 'DBA', 'USER')")
public String adminOrDbaOrUser(){
return "hello admin or dba or user";
}
}
Controller:
@RestController
public class HelloController {
@Autowired
MethodService methodService;
@GetMapping("/admin")
public String admin(){
return methodService.admin();
}
@GetMapping("/adminAndDba")
public String adminAndDba(){
return methodService.adminAndDba();
}
@GetMapping("/adminOrDbaOrUser")
public String adminOrDbaOrUser(){
return methodService.adminOrDbaOrUser();
}
}
配置角色:
@Configuration
public class MyWebSecurityConfig6 extends WebSecurityConfigurerAdapter {
@Bean
PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("root").password("123").roles("ADMIN", "DBA")
.and()
.withUser("admin").password("123").roles("ADMIN", "USER")
.and()
.withUser("sang").password("123").roles("USER");
}
}
测试:
- root用户: 可以访问全部三个路径:
-
admin用户: 可以访问"/admin"、"/adminOrDbaOrUser"
-
sang用户: 只能访问"/adminOrDbaOrUser"路径: