1、这篇文章资源来源于尚硅谷,不太适合入门者。
2、有了一定的基础再来。
第一部分
一、了解部分
1、SpringSecurity简介
这么说吧,它是一款非常牛皮的安全框架,主要是干两个事情,认证(Authentication)
和授权(Authorization)
2、历史
它的历史,自己可以去搜索看一下,不讲了
3、优点
SpringSecurity 特点:
- 和 Spring 无缝整合。
- 全面的权限控制。
- 专门为 Web 开发而设计。
- 旧版本不能脱离 Web 环境使用。
- 新版本对整个框架进行了分层抽取,分成了核心模块和 Web 模块。单独
引入核心模块就可以脱离 Web 环境。
- 重量级。
4、同级别的框架
shiro,这个也是我后续会出的文章
5、搭配
shiro + ssm更好
SpringSecurity + SpringBoot/Spring Cloud
6、核心模块
二、案例
1、编写类
一定要记住下面这几类,大概就会伴随我们这一篇文章
- WebSecurityConfigurerAdapter:自定义Security策略
- AuthenticationManagerBuilder:自定义认证策略
- @EnableWebSecurity:开启WebSecurity模式
@Configuration
public class SecurityConfigextends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() // 表单登录
.and()
.authorizeRequests() // 认证配置
.anyRequest() // 任何请求
.authenticated(); // 都需要身份验证
}
}
2、重要的单词
1、主体:principal
使用系统的用户或设备或其他系统远程系统登录的用户等。大致就是谁使用系统,谁就时主体。
2、认证:authentication
权限管理系统确认一个主体的身份,允许主体进入系统。简单来说就是认证了能登录。
3、授权:authorization
就是你有什么样子的角色,然后你会有什么权利
3、SpringSecurity的原理
SpringSecurity本质是一个过滤链:
从启动是可以获取到过滤器链:
org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFil
ter
org.springframework.security.web.context.SecurityContextPersistenceFilter
org.springframework.security.web.header.HeaderWriterFilter
org.springframework.security.web.csrf.CsrfFilter
org.springframework.security.web.authentication.logout.LogoutFilter
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter
org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter
org.springframework.security.web.savedrequest.RequestCacheAwareFilter
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter
org.springframework.security.web.authentication.AnonymousAuthenticationFilter
org.springframework.security.web.session.SessionManagementFilter
org.springframework.security.web.access.ExceptionTranslationFilter
org.springframework.security.web.access.intercept.FilterSecurityInterceptor
重点有三个:
(1)FilterSecurityInterceptor
-
FilterSecurityInterceptor:是一个方法级的权限过滤器, 基本位于过滤链的最底部。
-
康康这个
- super.beforeInvocation(fi) 表示查看之前的 filter 是否通过。
- fi.getChain().doFilter(fi.getRequest(), fi.getResponse());表示真正的调用后台的服务。
(2)ExceptionTranslationFilter
- 是一个异常过滤器,用来处理在认证授权过程中抛出的异常
- 看这个
(3)UsernamePasswordAuthenticationFilter
- :对/login 的 POST 请求做拦截,校验表单中用户名,密码
- 来看这个
- 里面有一个方法:返回是
UserDetails
,是系统默认的用户(即:pincipal),当然我们也会编写继承自这个类的类
(4)单独来讲一下 UserDetailsService
这个类提供有一个方法,它会和我们的
principal和UserDetails有关系的,这里只要知道这个就好了,我们一般会编写一个User来实现UserDetails,配置SpringSecurity实现安全管理
public class User implements UserDetails {
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public String getPassword() {
return null;
}
@Override
public String getUsername() {
return null;
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return false;
}
}
(5)PasswordEncoder接口讲解
1、接口大概情况
public interface PasswordEncoder {
// 表示把参数按照特定的解析规则进行解析
String encode(CharSequence var1);
// 表示验证从存储中获取的编码密码与编码后提交的原始密码是否匹配。如果密码匹
配,则返回 true;如果不匹配,则返回 false。第一个参数表示需要被解析的密码。第二个
参数表示存储的密码。
boolean matches(CharSequence var1, String var2);
// 表示如果解析的密码能够再次进行解析且达到更安全的结果则返回 true,否则返回
false。默认返回 false。
default boolean upgradeEncoding(String encodedPassword) {
return false;
}
}
2、实现类
实现上面接口的有几个类,但是最出色的是下面这个类
- BCryptPasswordEncoder 是 Spring Security 官方推荐的密码解析器,平时多使用这个解析
器。 - BCryptPasswordEncoder 是对 bcrypt 强散列方法的具体实现。是基于 Hash 算法实现的单
向加密。可以通过 strength 控制加密强度,默认 10.
3、测试
@Test
public void test01(){
// 创建密码解析器
BCryptPasswordEncoder bCryptPasswordEncoder = new
BCryptPasswordEncoder();
// 对密码进行加密
String atguigu = bCryptPasswordEncoder.encode("atguigu");
// 打印加密之后的数据
System.out.println("加密之后数据:\t"+atguigu);
//判断原字符加密后和加密之前是否匹配
boolean result = bCryptPasswordEncoder.matches("atguigu", atguigu);
// 打印比较结果
System.out.println("比较结果:\t"+result);
}