同步操作将从 小牛肉/cs-wiki 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
上节我们简单体验了下Spring Security,但是现在只能有一个用户信息,我们这里希望可以配置多个账号信息,本节主要讲解下如何在内存中配置认证信息。
定义一个配置类 WebSecurityConfig
,继承 WebSecurityConfigurerAdapter
,如下代码:
@Configuration
@EnableWebSecurity // 开启Spring Security的功能
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// 认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/*
* 配置为从内存中进行加载认证信息.
* 这里配置了两个用户 admin和user
*/
auth.inMemoryAuthentication().withUser("admin").password("123456").roles();
auth.inMemoryAuthentication().withUser("user").password("123456").roles();
}
}
🚨 如果是 5.x 之前的版本的话,那么到这里启动的话,就可以正常访问了,但是如果是 5.x 的版本的话,可以正常启动,但是在登录页面输入账号进行访问的话,会报如下错误:
java.lang.IllegalArgumentException:There is no PasswordEncoder mapped for the id "null"
这是因为 Spring Security 5.0中新增了多种加密方式,也改变了密码的格式。我们需要指定加密方式 👇
在 AuthenticationManagerBuilder
的方法中就可以指定加密方式了,如下代码:
auth.inMemoryAuthentication()
.passwordEncoder(new BCryptPasswordEncoder())
.withUser("admin")
.password(new BCryptPasswordEncoder().encode("123456"))
.roles();
auth.inMemoryAuthentication()
.passwordEncoder(new BCryptPasswordEncoder())
.withUser("user")
.password(new BCryptPasswordEncoder().encode("123456"))
.roles();
Bcrypt: bcrypt是一种跨平台的文件加密工具。bcrypt 使用的是布鲁斯·施内尔在1993年发布的 Blowfish 加密算法。由它加密的文件可在所有支持的操作系统和处理器上进行转移。它的口令必须是8至56个字符,并将在内部被转化为448位的密钥。
在 WebSecurityConfig
配置类中,通过 @Bean
注入 PasswordEncoder
具体的实现类,如下代码:
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
加入这个之后,需要修改密码加密:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/*
* 配置为从内存中进行加载认证信息.
* 这里配置了两个用户 admin和user
*/
auth.inMemoryAuthentication()
.withUser("admin")
.password(passwordEncoder().encode("123456"))
.roles();
auth.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder().encode("123456"))
.roles();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
对于上面的两种方式,推荐使用第二种方式,这种方式一方面更容易理解,另外代码扩展性更强。
上面我们基于内存的方式,构建了两个账号 admin 和 user,对于这两个账号在实际项目中会有不同的角色,比如管理员角色和普通用户角色,对于不同的角色,那么允许访问的方法会不一样。
通过 AuthenticationManagerBuilder
的 roles()
方法分配角色:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/*
* 配置为从内存中进行加载认证信息.
* 这里配置了两个用户 admin和user
*/
auth.inMemoryAuthentication()
.withUser("admin")
.password(passwordEncoder().encode("123456"))
.roles("admin");
auth.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder().encode("123456"))
.roles("normal");
}
想要开启 Spring 方法级安全,你需要在已经添加了 @Configuration
注解的类上再添加 @EnableGlobalMethodSecurity
注解:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
}
prePostEnabled
:决定 Spring Security 的前注解是否可用 [@PreAuthorize
,@PostAuthorize
,..]
即只有添加了@EnableGlobalMethodSecurity(prePostEnabled=true)
之后,@PreAuthorize("hasAnyRole('admin')")
才能生效。
secureEnabled
: 决定是否 Spring Security 的保障注解 [@Secured
] 是否可用。
jsr250Enabled
:决定 JSR-250 annotations 注解[@RolesAllowed
..] 是否可用。
我们在 HelloController
添加两个方法,使用注解 @PreAuthorize
指定访问该方法需要的角色:
@RestController
public class HelloController {
@RequestMapping("/hello")
public String hello() {
return "Hello,Spring Security";
}
@RequestMapping("/helloAdmin")
@PreAuthorize("hasAnyRole('admin')") // 只允许角色 admin 访问
public String helloAdmin() {
return "Hello,admin";
}
@RequestMapping("/helloUser")
@PreAuthorize("hasAnyRole('admin','normal')") // 允许角色 admin 和 normal 访问
public String helloUser() {
return "Hello,user";
}
}
访问如下地址:http://127.0.0.1:8080/helloUser,跳转到登录页面,输入账号 user/123456,成功登录之后,会看到返回信息:Hello,user
然后在输入另外一个地址:http://127.0.0.1:8080/helloAdmin,这时候会看到403的报错,因为该用户没有权限访问该方法
重新启动应用程序,输入 admin/123456 账号进行测试,都能正常访问。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。