SpringSecurity
1. 简介
Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。也就是一个权限框架。
2. 核心功能
- 用户认证(Authentication):检验用户名和密码的过程,判断用户是否已经登陆。
- 用户授权(Authorization):判断用户是否有权限访问。
3. 基本原理
本质上是一个过滤器(filter)。
- 如果基于session,那么会对cookie的SessionId进行解析。根据SessionId在服务器上进行查找,判断是否符合要求。
- 如果基于token,则会解析token,然后将请求加入到springsecurity管理的权限中去。
4.springboot项目中引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
5. 配置登陆名和密码
- 默认配置:拦截后会自动跳转默认的登陆页面,用户名为user,密码为控制台显示的一串字符。
- 配置文件配置:application.properties
spring.security.user.name=xxx
spring.security.user.password=xxx
内存中配置
- 自定义类继承WebSecurityConfigurerAdapter
重写configure(AuthenticationManagerBuilder auth)
- 注意:密码必须加密,不加密会无法通过校验,控制台报错:Encode Password does not look like BCrypt. 下面的BCryptPasswordEncoder也需要加载到容器中。
MyWebSecurityConfig
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 内存中虚拟用户
String password = bCryptPasswordEncoder.encode("123456");
System.out.println(password);
auth.inMemoryAuthentication().withUser("hello").password(password).roles("admin");
}
@Bean
BCryptPasswordEncoder getBCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
自定义实现(常用):数据库中查询用户名和密码
- 自定义类 MyUserDetailsService 实现 UserDetailsService 接口。
- 重写 loadUserByUsername (String s) 方法。
- 数据库查询用户信息。
- return user。
MyWebSecurityConfig
@Configuration
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
UserDetailsService myUserDeetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//需要一个UserDetailsService的实现类
auth.userDetailsService(myUserDeetailsService);
}
@Bean
BCryptPasswordEncoder getBCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
MyUserDetailsService
@Service("myUserDeetailsService")
public class MyUserDetailsService implements UserDetailsService {
@Autowired
BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
@Qualifier("userService")
UserService userService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
List auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_admin");
QueryWrapper qw = new QueryWrapper();
qw.eq("username", username);
vip.zhguo.springsecurity.pojo.User one = userService.getOne(qw);
// System.out.println(one.toString());
if (one == null)
throw new UsernameNotFoundException("用户名不存在");
return new User(one.getUsername(), bCryptPasswordEncoder.encode(one.getPassword()), auth);
}
}
6. 修改默认登陆界面
在MyWebSecurityConfig中重写configure(HttpSecurity http)
@Override
protected void configure(HttpSecurity http)throws Exception{
http.formLogin().loginPage("/login.html") //设置登陆页面
.loginProcessingUrl("/login") //设置登陆页面提交登陆请求的地址
.defaultSuccessUrl("/index") //登陆成功后跳转的路径
.permitAll() //放行
.and()
.authorizeRequests()
.antMatchers("/","/login.html") //设置的页面不会拦截
.permitAll()
.and()
.csrf().disable() //关闭csrf保护
.authorizeRequests()
.antMatchers("/admin/**").hasRole("admin") //是否具有admin角色
.antMatchers("/admin/**").hasAnyRole("admin","root") //admin和root角色任意一个就行
.antMatchers("/admin/**").hasAuthority("admin") //是否具有admin权限
.antMatchers("/admin/**").hasAnyAuthority("admin","root")//admin和root权限任意一个就行
.anyRequest().authenticated(); //其他都需要拦截认证。
}
注意:.authorizeRequests().antMatchers("/admin/**") 搭配使用,role默认会加ROLE_前缀,commaSeparatedStringToAuthorityList就需要加前缀
@Service("myUserDeetailsService")
public class MyUserDeetailsService implements UserDetailsService {
@Autowired
BCryptPasswordEncoder bCryptPasswordEncoder;
@Autowired
@Qualifier("userService")
UserService userService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
List auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_admin");
QueryWrapper qw = new QueryWrapper();
qw.eq("username", username);
vip.zhguo.springsecurity.pojo.User one = userService.getOne(qw);
// System.out.println(one.toString());
if (one == null)
throw new UsernameNotFoundException("用户名不存在");
return new User(one.getUsername(), bCryptPasswordEncoder.encode(one.getPassword()), auth);
}
}
后面还有基于注解的,实际不便于维护,就过了。