这里写自定义目录标题
- 前言
- Spring Security 是什么 ?
- 为什么使用Security ?
- 实现登陆拦截器
- 步骤
- 权限分配
- MD5加密密码
- 注解
- security 劣势
前言
分享一波权限知识 ~ ,Who可以对What进行How的访问操作
Spring Security 是什么 ?
- Security是安全的意思
- Spring Security 是提供安全的框架
- 她是基于Servlet过滤器,IOC和AOP
- 他的主要作用就是为了web请求和访问提供了身份确认和授权处理, 避免了很多重复性代码,减少了业务逻辑, 直接调用ApI就可以
为什么使用Security ?
轻松扩展并且满足自定义要求
api方便
实现登陆拦截器
Security组件
- SecurityContextHolder: 提供对SecurityContext 的访问
- SecurityContext 持有Authentication 对象和其他可能需要的信息
- AuthenticationManager 其中可以包含多个AuthenticationProvider
- ProviderManager对象为AuthenticationManager接口的实现类
- AuthenticationProvider 主要用来进行认证操作的类 调用其中的authenticate()方法去进行认证操作
- Authentication:Spring Security方式的认证主体
- GrantedAuthority:对认证主题的应用层面的授权,含当前用户的权限信息,通常使用角色表示
- UserDetails:构建Authentication对象必须的信息,可以自定义,可能需要访问DB得到
- UserDetailsService:通过username构建UserDetails对象,通过loadUserByUsername根据userName获取UserDetail对象 (可以在这里基于自身业务进行自定义的实现 如通过数据库,xml,缓存获取等)
步骤
- 引入pom文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
在这个过程中我遇到一个小问题,springboot项目启动的时候,发现启动之后自动停止运行,真的是郁闷了, 最后发现是自己没有在pom文件加入web pom文件,警告一下自己吧~
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 创建 SpringSecurityConfig 继承WebSecurityConfigurerAdapter
重新config方法
表示拦截js和css和images
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/js/**","/css/**","/images/**");
}
对用户进行验证
/**
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
//定义的简单规则
http.authorizeRequests()
//路径所有./
.antMatchers("/").permitAll()
//被认证
.anyRequest().authenticated()
.and()
//运行进行表单认证
.logout().permitAll()
.and()
.formLogin();
//关闭csrf的认证
http.csrf().disable();
}
```js
请求检测
@RestController
@EnableAutoConfiguration
public class DemoApplication {
@RequestMapping("/hello")
public String hello(){
return "hello word";
}
}
@RequestMapping("/hello")
public String hello(){
return "hello word";
}
当访问localhost:8080/hello 的时候她会直接让你调到login登陆
权限分配
通过上面的描述我们知道spring Security api实现了拦截必须登录才可以访问, 假如我们现在根据不同用户有访问接口的不同权限,这个时候如何?
请求的方法上加上@PreAuthorize , 当角色为admin的时候才可以访问api roleAuth ,否则不可以访问
//这句话的意思是启用@PreAuthorize 这个注解,在启动类上面加上
@EnableGlobalMethodSecurity(prePostEnabled = true)
//表示告诉应用与那个权限
@PreAuthorize("hasRole('ROLE_ADMIN')")
@RequestMapping("/roleAuth")
public String roleAuth(){
return "admin role";
}
需要说明的是我们必须在前缀上加上Role
public class RoleVoter implements AccessDecisionVoter<Object> {
private String rolePrefix = "ROLE_";
有两个角色,一个admin一个user
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(new MypasswordEncoder()).withUser("admin").password("123456").roles("ADMIN");
auth.inMemoryAuthentication().passwordEncoder(new MypasswordEncoder()).withUser("admin1").password("123456").roles("ADMIN");
auth.inMemoryAuthentication().passwordEncoder(new MypasswordEncoder()).withUser("admin2").password("123456").roles("USER");
}
如果这个时候我们跟数据库打交道
@Component
public class MyUserService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
return null;
}
}
MD5加密密码
为了安全我们要对密码进行加密,创建类MypasswordEncoder, 实现接口 PasswordEncoder
/**
* 加密方法,表示对原始密码进行加密
* @param charSequence
* @return
*/
@Override
public String encode(CharSequence charSequence) {
Md5PasswordEncoder md5PasswordEncoder = new Md5PasswordEncoder();
return md5PasswordEncoder.encodePassword(charSequence.toString(),"123456");
}
/**
* 匹配方法
* @param charSequence
* @param s
* @return
*/
@Override
public boolean matches(CharSequence charSequence, String s) {
return s.equals(charSequence.toString());
}
具体的方法myUserService
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 表示登陆的时候使用那个做个类去做关于数据库方法的权限
auth.userDetailsService(myUserService).passwordEncoder(new MypasswordEncoder());
}
注解
// 方法执行之后做权限认证
@PostAuthorize("hasRole()")
@PreFilter和@PostFilter可以对集合类型的参数或返回值进行过滤, @preFilter表示针对那个参数, @postFilter表示针对当前返回的对象
security 劣势
- 不太容易控制, 虽然写起来可以调用别人的api
- 需要使用注解来控制