一、基本认识
1.概念
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
2.相关单词
|Authorization :授权
Authentication :认证(登录)
WebSecurityConfigurerAdapter : web安全配置类(认证授权配置)
@EnableWebSecurity :开启web安全配置
HttpSecurity : http安全配置比如:放行
permitAll : 放行
antMatchers : 用来匹配某些url路径 ; antMatchers(“/login”).permitAll()
UserDetailsService :用户详情服务(用来加载数据库的用户数据) UserDao
SecurityContext : Security上下文工具,保存得有认证成功之后的用户信息
3.RBAC模型
RBAC是基于角色的访问控制(Role-Based Access Control )在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便。
二、使用
1.导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2.登录成功跳转控制器
@Controller
public class AuthController {
//登录成功后重定向地址
@RequestMapping("/loginSuccess")
@ResponseBody
public String loginSuccess(){
return "登录成功";
}
}
3.配置SpringSecurity
SpringSecurity提供了一个配置类WebSecurityConfigurerAdapter用来提供给程序员对SpringSecurity做自定义配置,我们需要配置如下几个信息:
- 创建UserDetailService的Bean,该组件是用来加载用户认证信息
- 配置编码器,通过该编码器对密码进行加密匹配
- 授权规则配置,哪些资源需要什么权限
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//提供用户信息,这里没有从数据库查询用户信息,在内存中模拟
@Bean
public UserDetailsService userDetailsService(){
InMemoryUserDetailsManager inMemoryUserDetailsManager =
new InMemoryUserDetailsManager();
inMemoryUserDetailsManager.createUser(User.withUsername("zs").password("123").authorities("admin").build());
return inMemoryUserDetailsManager;
}
//密码编码器:不加密
@Bean
public PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
//授权规则配置
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests() //授权配置
.antMatchers("/login").permitAll() //登录路径放行
.anyRequest().authenticated() //其他路径都要认证之后才能访问
.and().formLogin() //允许表单登录
.successForwardUrl("/loginSuccess") // 设置登陆成功页
.and().logout().permitAll() //登出路径放行 /logout
.and().csrf().disable(); //关闭跨域伪造检查
}
}
三、基于数据库的登录
1.定义UserDetailsService
- UserDetailsService : 是SpringSecurity提供用来获取认证用户信息(用户名,密码,用户的权限列表)的接口,我们可以实现该接口,复写loadUserByUsername(username)方法加载我们数据库中的用户信息
UserDetails是SpringSecurity用来封装用户认证信息,权限信息的对象,我们使用它 的实现类User封装用户信息 并返回,我们这里从数据库查询用户名
基于入门案例进行修改
- 准备好认证表t_login(密码密文) ,集成MyBatis等,做好准备工作
- 创建类UserDetailServiceImpl实现UserDetailsService接口
@Service
public class UserDetailServiceImpl implements UserDetailsService {
/**
* 加载数据库中的认证的用户的信息:用户名,密码,用户的权限列表
* @param username: 该方法把username传入进来,我们通过username查询用户的信息
(密码,权限列表等)然后封装成 UserDetails进行返回 ,交给security 。
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
...省略...
//密码是基于BCryptPasswordEncoder加密的密文
//User是security内部的对象,UserDetails的实现类 ,
//用来封装用户的基本信息(用户名,密码,权限列表)
return new User(username,loginFromMysql.getPassword(),permissions);
}
}
2. 定义密码编码器
@Bean
public PasswordEncoder passwordEncoder(){
//return NoOpPasswordEncoder.getInstance();
return new BCryptPasswordEncoder();
}
3.登录页面
准备登录页面static/login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登陆</title>
</head>
<body>
<h1>登陆</h1>
<form method="post" action="/login">
<div>
用户名:<input type="text" name="username">
</div>
<div>
密码:<input type="password" name="password">
</div>
<div>
<button type="submit">立即登陆</button>
</div>
</form>
</body>
</html>
4.配置登录页面
在WebSecurityConfig配置类中配置登陆页面和登陆请求地址
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/login").permitAll() //登录路径放行
.antMatchers("/login.html").permitAll() //对登录页面跳转路径放行
.anyRequest().authenticated() //其他路径都要拦截
.and().formLogin() //允许表单登录, 设置登陆页
.successForwardUrl("/loginSuccess") // 设置登陆成功页
.loginPage("/login.html") //登录页面跳转地址
.loginProcessingUrl("/login") //登录处理地址(必须)
.and().logout().permitAll(); //登出
}
- http.csrf().disable() :屏蔽跨域伪造检查
- antMatchers(“/login.html”).permitAll() : 对登录页面跳转路径放行
- loginPage(“/login.html”) :登录页面跳转地址(必须)
- loginProcessingUrl(“/login”) :登录处理地址(必须)
注意:前后端分离的项目中,其实后台是不需要登录页面的