Spring Security
1. 实现过程
1.1 依赖及配置
依赖
1 2 3 4
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
|
两种配置
用户信息存储
1.2 UserDetails
使用Spring Data存储库来保存用户
定义领域对象:User,实现了UserDetails接口,Spring Security就可以做到基于用户名密码进行认证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class User implements UserDetails { ... }
public interface UserDetails extends Serializable { Collection<? extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled(); }
|
定义持久化接口:UserRepository
,增加自定义方法:findByUsername
1.3 UserDetailsService
在配置类中添加 Bean,提供接口实现,Spring可以用于从用户名获取用户信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| @Bean public UserDetailsService userDetailsService(UserRepository userRepo) { return username -> { User user = userRepo.findByUsername(username); if (user != null) { return user; } throw new UsernameNotFoundException( "User '" + username + "' not found"); }; }
public interface UserDetailsService { UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException; }
|
1.4 PasswordEncoder
提供密码转换器,保证安全
1 2 3 4
| @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }
|
1.5 创建自定义登录页
当需要认证时转向的登录页:.loginPage("/login")
视图控制器,定义login请求对应的视图:registry.addViewController("/login");
登录的post请求由Spring Security自动处理,名称默认:username、password,可配置
1.6 保护Web请求
在 Controller 前处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .authorizeRequests() .mvcMatchers("/design", "/orders").hasRole("USER") .anyRequest().permitAll() .and() .formLogin() .loginPage("/login") .and() .logout() .logoutSuccessUrl("/") .and() .csrf() .ignoringAntMatchers("/h2-console/**") .and() .headers() .frameOptions() .sameOrigin() .and() .build(); }
|
2. 权限分类
Authority,权限
Role,角色,===>>>权限,加前缀:ROLE_
1 2 3 4 5
| @Override public Collection<? extends GrantedAuthority> getAuthorities() { return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")); }
|
3. 实现方法级别的安全
1 2 3 4 5 6 7 8 9
| @Configuration @EnableGlobalMethodSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter {}
@PreAuthorize("hasRole('ADMIN')") public void deleteAllOrders() { orderRepository.deleteAll(); }
|
4. 获取当前登录的用户
Principal
1 2 3 4 5 6
| @ModelAttribute(name = "user") public User user(Principal principal) { String username = principal.getName(); User user = userRepo.findByUsername(username); return user; }
|
@AuthenticationPrincipal
1 2 3 4 5 6
| @PostMapping public String processOrder(@Valid TacoOrder order, Errors errors, SessionStatus sessionStatus, @AuthenticationPrincipal User user) { ... }
|
安全上下文获取
1 2 3
| Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); User user = (User) authentication.getPrincipal();
|