一、Authentiation和AuthorizationAuthentiation认证就像公司门口的保安:Authentication auth = new UsernamePasswordAuthenticationToken( "zhangsan", "123456", List.of(new SimpleGrantedAuthority("ROLE_EMPLOYEE")) );SecurityContextHolder.getContext().setAuthentication(auth);认证解决"你是谁"的问题
常见方式: 用户名密码、OAuth2、JWT
成功后生成Authentication对象
Authorization就像公司的门禁, 不是每间房间都能随便进的.@PreAuthorize("hasRole('ADMIN')") public void deleteUser(Long userId) { }授权解决"你能干什么"的问题
通常通过注解或配置实现
二、SecurityContext和SecurityContextHolderAuthentication currentAuth = SecurityContextHolder.getContext().getAuthentication();
String username = currentAuth.getName();Object principal = currentAuth.getPrincipal();Collection<? extends GrantedAuthority> authorities = currentAuth.getAuthorities();三、UserDetails和UserDetailsServicepublic class MyUser implements UserDetails { private String username; private String password; private List<GrantedAuthority> authorities;
@Override public boolean isAccountNonExpired() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } }@Servicepublic class MyUserService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) { return new MyUser(username, encodePassword("123456"), List.of(new SimpleGrantedAuthority("USER"))); }}List<GrantedAuthority> authorities = AuthorityUtils .createAuthorityList("ROLE_ADMIN", "user:delete");
if (auth.getAuthorities().contains(new SimpleGrantedAuthority("user:delete"))) { }角色前缀ROLE_是Spring的约定
推荐权限命名格式为: 资源:操作(如product:read)
这是穿插一下RBAC的概念:
RBAC(Role-Based Access Control)是基于角色的访问控制, 核心思想是把权限赋予角色,再把角色赋予用户.
用户:
public class User { private Long id; private String username; private Set<Role> roles; }角色:
public class Role { private String code; private String name; private Set<Permission> permissions;}权限:
public class Permission { private String resource; private String action; private String code; }资源:
@RestController@RequestMapping("/orders")@PreAuthorize("hasAuthority('order:read')") public class OrderController { @DeleteMapping @PreAuthorize("hasAuthority('order:delete')") public void deleteOrder() {...}}