一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情。
1. SpringSecurity快速入门
- 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
- 编写controller验证
@RestController
@RequestMapping("/test")
public class TestController{
@GetMapping("hello")
public String hello(){
return "hello security";
}
}
2. SpringSecurity基本原理
- SpringSecurity本质上是一个过滤器链。
- 过滤器的典型代表:
- FilterSecurityInterceptor:是一个方法级的权限过滤器,基本位于过滤链的最底部。
- ExceptionTranslationFilter:是个异常过滤器,用来处理在认证授权过程中抛出的异常。
- UsernamePasswordAuthenticationFilter:对/login的POST请求做拦截,校验表单中用户名,密码。
- SpringSecurity重要接口
- UserDetailsService接口:查询数据库用户名和密码过程
- PasswordEncoder接口:数据加密接口
3. 自定义配置类
- 定义UsersMapper接口
@Mapper
public interface UsersMapper extends BaseMapper<Users> {}
- 实现UserDetailsService接口
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService{
@Autowired
private UsersMapper usersMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException{
QueryWrapper<Users> wrapper = new QueryWrapper();
wrapper.eq("username");
Users users = usersMapper.selectOne(wrapper);
if(users==null){ // 数据库没有用户名,认证失败
throw new UsernameNotFoundException("用户名不存在!");
}
List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("admins,ROLE_sale,ROLE_admin");
return new User(users.getUsername(), new BCryptPasswordEncoder().encode(users.getPassword()), auths);
}
}
- 编写配置类
public class SecurityConfigTest extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autorwird
private DataSource dataSource;
@Bean
public PersistentTokenRepository persistentTokenRepository(){
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
return jdbcTokenRepository;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception{
auth.userDetailService(userDetailsService).passwordEncoder(password());
}
@Bean
PasswordEncoder password() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception{
//自定义编写的登录页面
http.formLogin()
.loginPage("/login.html") //登录页面设置
.loginProcessingUrl("/user/login") //登录访问路径
.defaultSuccessUrl("/test/index").permitAll() //登录成功之后,跳转路径
.and().authorizeRequests()
.antMatchers("/","/text/hello","/user/login") //设置哪些路径可以直接访问,不需要认证
.antMatchers("/test/index").hasAuthority("admins") // 当前登录用户只有具有admins权限才可以访问这个路径
.antMatchers("/test/index").hasAnyAuthority("admins,manager") //设置多个权限
.antMatchers("/test/index").hasRole("sale")
.and().rememberMe().tokenRepository(persistentTokenRepository()) // 自动登录功能(记住我)
.tokenValiditySeconds(60)
.userDetailsService(userDetailsService)
.anyRequest().authenticated() // 设置所有请求都不需要认证
.and().csrf().disable(); //关闭csrf防护
//自定义403页面
http.exceptionHandling().accessDeniedPage("/unauth.html");
//自定义注销
http.logout().logoutUrl("/user/logout")
.loginSuccessUrl("test/hello").permitAll();
}
}