SpirngSecurity
原理
三个过滤器(过滤器链)
FilterSecurityInterceptor:方法过滤器
ExceptionTranslationFilter:异常过滤器
UsernamePasswordAuthenticationFilter:对/login的post请求拦截,校验表单中用户名,密码。
…
过滤器加载:
DelegatingFilterProxy来加载所有的过滤器
两个重要接口:
UserDetailsService接口:实现这个接口来从数据库查找用户名和密码。
1.创建类继承UsernamePasswordAuthenticationFilter,重写三个方法
2.创建类实现UserDetailsService
PasswordEncoder
数据加密接口
设置用户名密码
配置文件:
spring.security.user.name=zzz
spring.security.user.password=123456
配置类的形式
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String encode = bCryptPasswordEncoder.encode("123");
auth.inMemoryAuthentication().withUser("zzz").password(encode).roles("admin");
}
@Bean//一定要注入PasswordEncoder对象---不太能理解
PasswordEncoder password() {
return new BCryptPasswordEncoder();
}
}
自定义接口实现类
@Configuration
public class SecurityConfigMethod extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(password());
}
@Bean
PasswordEncoder password() {
return new BCryptPasswordEncoder();
}
}
//实现接口来实现从数据库查找值
@Service("userDetailsService")
public class MyUserDetailService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
return new User("mary",new BCryptPasswordEncoder().encode("123"),auths);
}
}
自定义设置登录页面不需要认证可以访问
1.配置类实现
//在配置类实现相关配置,继承WebSecurityConfigurerAdapter方法
@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防护
}
基于角色或权限进行访问控制
hasAuthority
@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() //设置哪些路径可以直接访问,不需要认证
//当前登录用户,只有具有admins权限才可以访问路径,用户权限是在userDetailsService接口实现添加的
.antMatchers("/test/index").hasAuthority("admins")
.anyRequest().authenticated()
.and().csrf().disable();//关闭csrf防护
}
//userDetailsService设置用户角色
List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("admins");
hasAnyAuthority
//当前用户只要有其中某一个权限就可以访问
.antMatchers("/test/index").hasAnyAuthority("admins,manager")
hasRole
//hasRole方法,用户前面需要+ROLE_
.antMatchers("/test/index").hasRole("rale")
private static String hasRole(String role) {
Assert.notNull(role, "role cannot be null");
if (role.startsWith("ROLE_")) {
throw new IllegalArgumentException(
"role should not start with 'ROLE_' since it is automatically inserted. Got '"
+ role + "'");
}
return "hasRole('ROLE_" + role + "')";
}
asAnyRole()同理
//配置没有权限访问跳转自定义页面
http.exceptionHandling().accessDeniedPage("/unauth.html");
认证授权注解
//1.启动类开启注解
@SpringBootApplication
@MapperScan("com.zyq.mapper")
@EnableGlobalMethodSecurity(securedEnabled = true)
public class Securitydemo1Application {
}
//2.controller方法使用注解,设置角色
@GetMapping("/update")
@Secured({"ROLE_sale","admin"})
public String update() {
return "hello update";
}
//3.userDetailsService设置用户角色
List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("admins");