spring.security.user.name=root
spring.security.user.password=root
package cn.knightzz.security.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* @author knightzz
* @date 2021/3/5 10:59
*/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encodePassword = passwordEncoder.encode("root");
auth.inMemoryAuthentication().withUser("root")
.password(encodePassword).roles("admin");
}
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
步骤
第一步 : 创建配置 设置使用哪个 userDaoService实现类
第二步 : 编写实现类 返回user对象(包括用户密码以及操作权限)
代码
第一步 : 创建相关配置
package cn.knightzz.security.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* @author knightzz
* @date 2021/3/5 11:51
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsService userDetailsService;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
第二步 : 编写 Service 类
package cn.knightzz.security.service;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author knightzz
* @date 2021/3/5 11:57
*/
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
// 模拟生成权限列表
List<GrantedAuthority> auths = AuthorityUtils.
commaSeparatedStringToAuthorityList("role");
// 账号 , 密码, 权限集合
return new User("root" ,new BCryptPasswordEncoder().encode("root"),auths);
}
}
添加相关配置
package cn.knightzz.security.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* @author knightzz
* @date 2021/3/5 11:51
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsService userDetailsService;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() // 自定义自己编写的登陆页面
.loginPage("/login.html") // 登陆页面设置
.loginProcessingUrl("/user/login") // 登陆访问路径
.defaultSuccessUrl("/test/index").permitAll() // 登陆成功以后的跳转路径
.and().authorizeRequests()
.antMatchers("/", "/test/hello","/user/login").permitAll() // 设置哪些路径不需要认证可以直接访问
.anyRequest().authenticated()
.and().csrf().disable(); // 关闭csrf防护
}
}
编写登陆页面
登陆页面是在 static 目录下
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登陆title>
head>
<body>
<form action="/user/login" method="post">
用户名 : <input name="username" type="text">
<br />
密码 : <input name="password" type="text">
<br/>
<input type="submit" value="login">
form>
body>
html>
测试
http://localhost:8111/test/index
第一步 在配置类中设置当前访问地址有哪些权限
// 当前登录用户 必须有admin 权限才可以访问
.antMatchers("/test/admin").hasAnyAuthority("admin")
第二步 在 UserDetailsService 设置相应权限
// 模拟生成权限列表
List<GrantedAuthority> auths = AuthorityUtils.
commaSeparatedStringToAuthorityList("admin");
// 账号 , 密码, 权限集合
return new User("root" ,new BCryptPasswordEncoder().encode("root"),auths);
测试
http://localhost:8111/test/admin
# 如果没有权限的话 结果 会报错 :
Whitelabel Error Page
There was an unexpected error (type=Forbidden, status=403).
// 作用
如果当前用户有提供的权限列表中的任何一个 返回 true
配置
// 当前用户必须要有权限列表中的任何一个都可以访问该路径
.antMatchers("/test/role").hasAnyAuthority("admin","superAdmin","role","user")
第二步 在 UserDetailsService 设置相应权限
// 模拟生成权限列表 用户角色使用 , 分割
List<GrantedAuthority> auths = AuthorityUtils.
commaSeparatedStringToAuthorityList("admin,user,superAdmin");
// 账号 , 密码, 权限集合
return new User("root" ,new BCryptPasswordEncoder().encode("root"),auths);
测试
http://localhost:8111/test/role
配置
// 需要有 ROLE_user 角色才能访问
.antMatchers("/test/role").hasRole("user")
第二步 在 UserDetailsService 设置相应权限
这里需要注意的是 角色列表 是 ROLE_ 开头的 否则会报错的
// 模拟生成权限列表
List<GrantedAuthority> auths = AuthorityUtils.
commaSeparatedStringToAuthorityList("ROLE_user");
测试
http://localhost:8111/test/role
使用方式 与 hasAnyAuthority 类似
添加配置
// 配置没有权限访问跳转到自定义页面
http.exceptionHandling().accessDeniedPage("/403.html");
创建403页面
<html lang="en">
<head>
<meta charset="UTF-8">
<title>403title>
head>
<body>
<h1>403 ! 没有访问权限h1>
body>
html>
测试
http://localhost:8111/test/role
作用
用户必须 具有某个角色才能访问方法
1. 使用前必须开启注解功能: 在启动类(或者配置类)上添加开启注解
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SpringSecurityWebApplication {}
2. 需要注意的是 匹配字符串需要添加前缀 "ROLE"
List<GrantedAuthority> auths = AuthorityUtils.
commaSeparatedStringToAuthorityList("ROLE_admin,admin");
第二步 : 在 Controller 的方法中添加注解
@Secured({"ROLE_admin", "ROLE_manager"})
@GetMapping("update")
public String update(){
return "hello update";
}
测试
http://localhost:8111/test/update
作用
注解适合进入方法前的验证
1. 需要开启注解
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SpringSecurityWebApplication {}
List<GrantedAuthority> auths = AuthorityUtils.
commaSeparatedStringToAuthorityList("ROLE_admin,admin");
第二步 : 在 Controller 的方法中添加注解
@PreAuthorize("hasAnyAuthority('admin')")
@GetMapping("auth")
public String preAuthorize(){
return "hello PreAuthorize";
}
测试
http://localhost:8111/test/auth
作用
1. 注解是在 方法执行后 才会验证权限的
2. 需要开启注解
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SpringSecurityWebApplication {}
List<GrantedAuthority> auths = AuthorityUtils.
commaSeparatedStringToAuthorityList("ROLE_admin,admin");
第二步 : 在 Controller 的方法中添加注解
@PostAuthorize("hasAnyAuthority('aaaa')")
@GetMapping("post_auth")
public String postAuthorize(){
System.out.println("postAuthorize");
return "hello postAuthorize";
}
测试
http://localhost:8111/test/post_auth
// 测试结果
403 ! 没有访问权限
// 控制台会打印 hello postAuthorize
作用
1. 权限验证之后对返回数据进行过滤
2. filterObject 对应返回值List的实体类 User
作用是 过滤掉 password 不等于 'admin01' 的数据 留下密码是 'admin01' 的数据
@GetMapping("user")
@PreAuthorize("ROLE_admin")
@PostFilter("filterObject.password == 'admin01'")
public List<User> getAllUser(){
第二步 : 在 Controller 的方法中添加注解
@GetMapping("user")
@PreAuthorize("ROLE_admin")
@PostFilter("filterObject.password == 'admin01'")
public List<User> getAllUser(){
List<User> users = new ArrayList<>();
users.add(new User("admin01", "12345"));
users.add(new User("admin02", "admin02"));
return users;
}
使用 postman 测试
http://localhost:8111/test/user
// 测试结果
[{"username":"admin02","password":"admin02"}]
作用
1. 进入控制器之前对传入数据进行过滤
2. 过滤掉 username 不等于 admin01 的数据 filterObject就是 users 的 User 类
@GetMapping("filter")
@PreAuthorize("hasAnyAuthority('ROLE_admin')")
@PreFilter("filterObject.username == 'admin01'")
public List<User> getTestPreFilter(List<User> users){}