spring security基本概念及实际应用
1、认证授权基本概念
1.1、什么是认证
认证就是校验一个用户是否合法,是否是存在的用户。
1.2、什么是授权
一些资源需要用户有指定的权限才可以访问。
1.3、什么是会话
用户登录成功后,为了避免后续用户的每次操作都再一次进行认证,把用户的信息储存起来。
1.4、授权的数据模型
授权可以理解为who对what进行how操作
who:用户或者程序
what:资源
how:权限
可以分成6张表

1.5、RBAC
访问控制分为两种:
- 基于角色的访问控制(Role-Based Access Control)
- 基于资源的访问控制(Resource-Based Access Control)
2、使用SpringBoot继承Spring Security
首先创建SpringBoot项目,引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
编写配置类
@Configuration
@EnableWebSecurity//启用Spring Security
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//为用户建立内存用户存储
@Bean
@Override
protected UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
//定义密码比对器
@Bean
public PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();// 不对密码进行加密
}
//核心配置,定义Spring Security如何对请求进行拦截
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()// 开始对请求进行处理
.antMatchers("/r/r1").hasAuthority("p1")// /r/r1请求必须有p1权限
.antMatchers("/r/r2").hasAuthority("p2")// /r/r2请求必须有p2权限
.antMatchers("/r/**").permitAll()// 后续/r/**请求全部放行
.antMatchers("/", "/home").permitAll()// /、/home不需要认证
.anyRequest().authenticated()// 其他所有请求都需要认证
.and()
.formLogin()
.loginPage("/login")// 指定登录页
.permitAll()
.and()
.logout()// 注销请求全部放行
.permitAll();
}
}
userDetailsService()方法直接在内存中定义了一个用户,但是大多数时候都希望从其他地方获取到用户。这时候可以定义一个UserDetailService的实现类,实现loadUserByUsername方法,在其中定义用户的验证规则。
@Service
public class SpringDataUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("username: " + username);
UserDetails userDetails = User.withUsername(username).password("$2a$10$unG4fq1zoSukMWA1Ie/U2.PG1WUHO5h6ai7aVWN59dk3CPdQgZnAm").authorities("p1").build();
return userDetails;
}
}
可以注入dao让其去数据库验证用户的有效性。
那么如果现在用户认证成功了,会话功能如何体现呢?
用户认证成功后,会把用户的相关信息存在Security上下文中,可以通过SecurityContextHolder.getContext().getAuthentication()获取到用户的信息。
/**
* 获取当前登录用户名
*/
public String getUsername(){
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// 如果没有认证返回null
if (!authentication.isAuthenticated()){
return null;
}
Object principal = authentication.getPrincipal();
String username = null;
if (principal instanceof UserDetails){
username = ((UserDetails)principal).getUsername();
} else {
username = principal.toString();
}
return username;
}
对资源拦截可以分成web拦截和方法层面的拦截。
现在是web拦截
.antMatchers("/r/r1").hasAuthority("p1")// /r/r1请求必须有p1权限
.antMatchers("/r/r2").hasAuthority("p2")// /r/r2请求必须有p2权限
在配置类上定义@EnableGlobalMethodSecurity可以启用方法拦截注解功能
比如可以加上如下配置
@EnableGlobalMethodSecurity(prePostEnabled = true)
在方法中加上
@PreAuthorize("hasAuthority('p1')")
那么在访问此方法时要求用户有p1权限

浙公网安备 33010602011771号