SpringSecurity简单理解与探讨
前言
在学习SpringSecurity之前,我们需要先了解到两个关键词,“认证"与"授权”。
众所周知,在我们项目中,安全尤为重要,而安全的两个核心便是上面两个关键词,即安全=“认证”+“授权”。
认证(Authentication)和授权(Authorization)
一般来说,应用访问安全性,都是围绕认证(Authentication)和授权(Authorization) 这两个核心展开。
认证(Authentication): 确定用户身份,验证该用户是否是本系统的用户,从而具体到哪一个用户。
授权(Authorization): 通过认证后,判断此用户是否用访问某些指定资源的权限。
什么是SpringSecurity
SpringSecurity能够为基于Spring的企业应用系统提供一套声明式的安全访问控制解决方案的安全框架,可以基于RBAC(基于角色的权限控制)对用户的访问进行权限控制。
核心:
- WebSecurityConfigurerAdapter:自定义security策略
- @EnableWebSecurity:启用WebSecurity
- AuthenticationManagerBuilder:自定义认证策略
其核心思想就是通过一系列的filter chain 来对用户的访问进行权限的相应控制。
参考官网: https://spring.io/projects/spring-security
快速入门
- 导入依赖
<!--导入SpringSecurity:安全机制-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
- 自定义安全配置
//启用安全机制
@EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
//授权
@Override
protected void configure(HttpSecurity http) throws Exception {
/**
* 设置首页所有人都可以访问,功能页只有对应权限的人才能访问
* permitAll():代表所有人
* hasRole():指定对应角色访问特定
* /level1/**:代表level下所有功能模块需要vip1用户才能访问
* csrf:跨站请求伪造Cross-site request forgery
*/
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2");
//没有权限默认会到登录页面
http.formLogin().loginPage("/login.html").loginProcessingUrl("/login").and()
.csrf().disable();
//注销,开启注销功能,返回首页
http.logout().logoutSuccessUrl("/");
}
//认证
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/**
* inMemoryAuthentication在内存中对用户名及密码进行认证
* passwordEncoder(new BCryptPasswordEncoder()):对密码进行加密操作
*/
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1", "vip2")
.and()
.withUser("zhangsan").password(new BCryptPasswordEncoder().encode("123")).roles("vip2");
}
}
- 测试Demo
项目启动后,有四个不同功能模块,当我们点击相应模块后,均需要对用户进行一个认证登录,此时若未认证登录的用户,将自动跳转到默认登录页面,进行登录操作。
实现自动跳转到默认登录页面
http.formLogin()
同时还提供了自定义登录页面
http.formLogin().loginPage("/login.html").loginProcessingUrl("/login")
loginPage():指定自定义登录页面
loginProcessingUrl():自定义登录页面表单请求路径
下文均采用自定义登录页面,样式未调,多多包涵!!!
此时我们使用admin用户进行登录,
由于admin分配了vip1,vip2两个角色,而在configure中,对level1,level2两个大模块下需要指定角色才有权限进行访问,通过roles(“vip1”, “vip2”)对用户admin进行角色的认证,所以对于四个模块admin用户均可以访问。
/**authorizeRequests():授权请求
antMatchers("/"):具体的请求
permitAll():所有人均可访问
hasRole("vip1"):指定角色进行访问
inMemoryAuthentication():在内存中设置用户测试
*/
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/level1/**").hasRole("vip1")
.antMatchers("/level2/**").hasRole("vip2");
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1", "vip2")
其中,注销功能的开启
//注销,开启注销功能,返回首页
http.logout().logoutSuccessUrl("/");
可以知道,我们在测试的过程中,采用的是在内存中设置初始值用户,下篇将采用连接数据库动态认证与授权。