文章目录
Spring Security基础内容
刚接触,试图理解
资源
创建
依赖导入:
<dependencies>
<!-- ... other dependency elements ... -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
指定版本:
不指定就用默认默认设置的版本
<properties>
<!-- ... -->
<spring-security.version>5.3.4.RELEASE</spring-security.version>
</dependencies>
特征:
- Authentication:鉴定,验证正在登录者的身份。
- Authorization:授权
- PasswordEncoder接口,像是存储密码的地方
SpringBoot自动做了三件事:
- 启用默认配置,创造了个过滤器
bean
,命名为springSecurityFilterChain
,这个bean对所有的安全负责。如URLs、验证用户名和密码、重定向等。 - 创建了一个
UserDetailsServcie
bean,用户名是user
,密码是随机的可以在console
的log
看到。 - 注册了一个过滤器
bean
,命名为springSecurityFilterChain
,是每个request
的Servlet
容器。
结构:
现在要做验证和鉴权的第一步:
创建自定义用户:
使用AuthenticationManagerBuilder
的inMemoryAuthentication()
方法在内存中创建,可设置用户名、密码、指定权限,注意密码需要加密。
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("admin").password(new BCryptPasswordEncoder().encode("pwd")).roles("USER","ADMIN");
完整代码:
configure(HttpSecurity)
部分可以看后面的解析。
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
// 利用参数不同做重载,auth是创建用户
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/**
* 在内存中创建一个名为 "user" 的用户,密码为 "pwd",拥有 "USER" 权限,密码使用BCryptPasswordEncoder加密
*/
// 看了文档还是有点用的,passwordEncoder是密码库,有不同的加密方式
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("user").password(new BCryptPasswordEncoder().encode("pwd")).roles("USER");
/**
* 在内存中创建一个名为 "admin" 的用户,密码为 "pwd",拥有 "USER" 和"ADMIN"权限
*/
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
.withUser("admin").password(new BCryptPasswordEncoder().encode("pwd")).roles("USER","ADMIN");
}
}
验证
自定义验证方法
-
首先,要能接收到前端输入的用户名和密码,并存储起来。
一个重要的实例:
将前端获取的用户的凭证(也就是密码)、细节、职务等信息保存起来,第一个方法就是获取用户的权限信息集合。public interface Authentication extends Principal, Serializable { Collection<? extends GrantedAuthority> getAuthorities(); Object getCredentials(); Object getDetails(); Object getPrincipal(); boolean isAuthenticated(); void setAuthenticated(boolean var1) throws IllegalArgumentException; }
-
有了用户信息之后,就可以进行验证了,这里自定义一个验证方法。
自定义验证类:
功能是只要用户名是alex
,就能通过验证,并加上ADMIN
和USER
权限。/** * Created by wxb on 2018/10/21 0021. * 自定义验证类,可以用作backdoor,例如输入:alex/任意密码就可以通过验证 */ @Component public class BackdoorAuthenticationProvider implements AuthenticationProvider { @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { // 这个方法是Principal的 String name = authentication.getName(); String password = authentication.getCredentials().toString(); //利用alex用户名登录,不管密码是什么都可以,伪装成admin用户 if (name.equals("alex")) { // 自己造了个,按理说应是getAuthorities()方法? Collection<GrantedAuthority> authorityCollection = new ArrayList<>(); authorityCollection.add(new SimpleGrantedAuthority("ROLE_ADMIN")); authorityCollection.add(new SimpleGrantedAuthority("ROLE_USER")); // 设置职务、密码、权限 // 有几个方法确实是继承了Authentication return new UsernamePasswordAuthenticationToken( "admin", password, authorityCollection); } else { return null; } } @Override public boolean supports(Class<?> authentication) { return authentication.equals( UsernamePasswordAuthenticationToken.class); } }
-
有了用户和自定义的验证方法,就可以走主验证程序了,要把自己定义的验证方法加进去。
主验证程序:
通过重写参数为AuthenticationManagerBuilder
类型的configure
,可以创建用户,同时添加自己设置的验证类,上面用了@Component
注释,所以可以自动装箱,加入到验证链ProviderManagerBuilder
中(AuthenticationManagerBuilder
实现了ProviderManagerBuilder
)。@EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired BackdoorAuthenticationProvider backdoorAuthenticationProvider; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { /** * 在内存中创建一个名为 "user" 的用户,密码为 "pwd",拥有 "USER" 权限,密码使用BCryptPasswordEncoder加密 */ auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("user").password(new BCryptPasswordEncoder().encode("pwd")).roles("USER"); /** * 在内存中创建一个名为 "admin" 的用户,密码为 "pwd",拥有 "USER" 和"ADMIN"权限 */ auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) .withUser("admin").password(new BCryptPasswordEncoder().encode("pwd")).