目录
一、设置登录系统的账号、密码
二、数据库查询用户名密码
三、自定义登录页面
四、基于角色或权限进行访问控制
(一)hasAuthority 方法
(二)hasAnyAuthority 方法
(三)hasRole 方法
(四)hasAnyRole
五、自定义403页面
六、注解使用
(一)@Secured
(二)@PreAuthorize
(三)@PostAuthorize
(四)@PreFilter
(五)@PostFilter
七、基于数据库的记住我
八、CSRF
方式一,配置文件application.properties
spring.security.user.name=lucy spring.security.user.password=123
方式二,编写配置类
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder(); String password = bCryptPasswordEncoder.encode("123"); auth.inMemoryAuthentication().withUser("zhangsan").password(password).roles("admin"); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
方式三,通过类实现接口UserDetailService
@Service public class userDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException Listlist = AuthorityUtils.commaSeparatedStringToAuthorityList("role"); return new User("zhangsan", new BCryptPasswordEncoder().encode("123"), list); } }
引入依赖
org.projectlombok lombokmysql mysql-connector-javacom.baomidou mybatis-plus-boot-starter3.0.5
建表sql
create table users( id bigint primary key auto_increment, username varchar(20) unique not null, password varchar(100) );
数据源配置
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/demo?serverTimezone= GMT%2B8 username: root password: 123456
实体类users
@Getter @Setter @AllArgsConstructor @NoArgsConstructor public class Users { private Integer id; private String username; private String password; }
mapper
@Mapper public interface UserMapper extends BaseMapper{ }
修改userDetailService
@Service public class userDetailsService implements UserDetailsService { @Autowired UserMapper userMapper; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { // 使用mapper查询数据库 QueryWrapperqueryWrapper = new QueryWrapper<>(); queryWrapper.eq("username", s); Users users = userMapper.selectOne(queryWrapper); if (users == null) { throw new UsernameNotFoundException("用户名不存在!"); } List list = AuthorityUtils.commaSeparatedStringToAuthorityList("role"); return new User(users.getUsername(), new BCryptPasswordEncoder().encode(users.getPassword()), list); } }
修改SecurityConfigTest
@Configuration public class SecurityConfigTest extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
在配置类SpringSecurity中重写configure方法
@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防护 }
再编写登录页面
Title
controlller
@RestController @RequestMapping("/test") public class HelloController { @GetMapping("/hello") public String test() { return "hello, security"; } @GetMapping("/index") public String index() { return "hello, index"; } }
启动项目后使用的登录页面就是我们编写的 了
如果当前的主体具有指定的权限,则返回 true,否则返回 false
设置访问/test/index需要admin角色
给用户添加admin角色
修改角色为别的,不是admin后访问被禁止
底层源码:
给用户添加角色需要加上前缀ROLE_
修改配置文件:
在配置类中配置
编写unauth页面
Title 没有访问权限
跳转成功
@SpringBootApplication @EnableGlobalMethodSecurity(securedEnabled=true) public class DemosecurityApplication { public static void main(String[] args) { SpringApplication.run(DemosecurityApplication.class, args); } }
controller
@GetMapping("/update") @Secured({"ROLE_admin"}) public String update() { return "hello, update"; }
@GetMapping("/update") @PreAuthorize("hasAnyAuthority('admin')") public String update() { return "hello, update"; }
@RequestMapping("/testPostAuthorize") @ResponseBody @PostAuthorize("hasAnyAuthority('admin')") public String preAuthorize(){ System.out.println("test--PostAuthorize"); return "PostAuthorize"; }
@RequestMapping("getTestPreFilter") @PreAuthorize("hasRole('ROLE_管理员')") @PreFilter(value = "filterObject.id%2==0") @ResponseBody public ListgetTestPreFilter(@RequestBody List list){ list.forEach(t-> { System.out.println(t.getId()+"\t"+t.getUsername()); }); return list; }
@RequestMapping("getAll") @PreAuthorize("hasRole('ROLE_管理员')") @PostFilter("filterObject.username == 'admin1'") @ResponseBody public ListgetAllUser(){ ArrayList list = new ArrayList<>(); list.add(new UserInfo(1l,"admin1","6666")); list.add(new UserInfo(2l,"admin2","888")); return list; }
使用spring security记住登录的用户原理
创建表
CREATE TABLE `persistent_logins` ( `username` varchar(64) NOT NULL, `series` varchar(64) NOT NULL, `token` varchar(64) NOT NULL, `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`series`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
配置文件编写数据库的配置
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/demo?serverTimezone= GMT%2B8 username: root password: 123456
配置类
Title