Spring Security + OAuth2
第一章 Spring Security 快速入門
第二章 Spring Security 自定義配置
第三章 Spring Security 前后端分離配置
第四章 Spring Security 身份認證
第五章 Spring Security 授權
第六章 OAuth2
文章目錄
- Spring Security + OAuth2
- 1、基于request的授權
- 1.1、用戶-權限-資源
- 需求
- 配置權限
- 授權權限
- 請求未授權的接口
- 1.2、用戶-角色-資源
- 配置角色
- 授權角色
- 1.3、用戶-角色-權限-資源
- 2、基于方法的授權
- 2.1、開啟方法授權
- 2.2、給用戶授予角色和權限
- 2.3、常用授權注解
授權管理的實現在SpringSecurity中非常靈活,可以幫助應用程序實現以下兩種常見的授權需求:
- 用戶-權限-資源:例如張三的權限是添加用戶、查看用戶列表、李四的權限是查看用戶列表
- 用戶-角色-權限-資源:例如張三是角色是管理員、李四的角色是普通用戶,管理員能做所有操作,普通用戶只能查看信息
1、基于request的授權
1.1、用戶-權限-資源
需求
- 具有USER_LIST權限的用戶可以訪問/user/list
- 具有USER_ADD權限的用戶可以訪問/user/add
配置權限
SecurityFilterChain
package com.security.demo.config;
import ...@Configuration //配置類
public class WebSecurityConfig {@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {// authorizeHttpRequests() 開啟授權保護// anyRequest() 對所以請求開啟授權保護// authenticated()已認證請求會自動授權。http.authorizeHttpRequests(authorize -> authorize//具有USER_LIST權限的用戶可以訪問/user/list .requestMatchers("/user/list").hasAnyAuthority("USER_LIST")//具有USER_ADD權限的用戶可以訪問/user/addd.requestMatchers("/user/add").hasAnyAuthority("USER_ADD")//對所有請求開啟授權保護.anyRequest()//已認證的請求會被自動授權.authenticated());...
}
授權權限
DBUserDetailsManager中的loadUserByUsername方法:
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {QueryWrapper<User> queryWrapper = new QueryWrapper();queryWrapper.eq("username",username);User user = userMapper.selectOne(queryWrapper);if (user==null){throw new UsernameNotFoundException(username);}else{Collection<GrantedAuthority> authorities = new ArrayList<>();//模擬權限authorities.add(()->"USER_LIST");authorities.add(()->"USER_ADD");return new org.springframework.security.core.userdetails.User(user.getUsername(),user.getPassword(),user.getEnabled(),true,//用戶賬號是否過期。true,//用戶憑證是否過期true,//未被鎖定authorities//權限列表);}}
請求未授權的接口
實現AccessDeniedHandler 接口
package com.security.demo.config;public class MyAccessDeniedHandler implements AccessDeniedHandler {@Overridepublic void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exception) throws IOException, ServletException {//創建結果對象HashMap result = new HashMap();result.put("code",-1);result.put("message","沒有權限");//轉換成json字符串String json = JSON.toJSONString(result);//返回響應response.setContentType("application/json;charset=UTF-8");response.getWriter().println(json);}
}
SecurityFilterChain添加配置請求未授權的處理。
package com.security.demo.config;
import ...@Configuration //配置類
public class WebSecurityConfig {@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {...http.exceptionHandling(exception -> {exception.accessDeniedHandler(new MyAccessDeniedHandler());//請求未授權的處理});...
}
1.2、用戶-角色-資源
配置角色
package com.security.demo.config;
import ...@Configuration //配置類
public class WebSecurityConfig {@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(authorize -> authorize.requestMatchers("/user/**").hasRole("ADMIN").anyRequest().authenticated());...
}
授權角色
@Component
public class DBUserDetailsManager implements UserDetailsManager, UserDetailsPasswordService {@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {QueryWrapper<User> queryWrapper = new QueryWrapper();queryWrapper.eq("username",username);User user = userMapper.selectOne(queryWrapper);if (user==null){throw new UsernameNotFoundException(username);}else{//模擬授權return org.springframework.security.core.userdetails.User.withUsername(user.getUsername()).password(user.getPassword()).disabled(!user.getEnabled())//用戶是否禁用.credentialsExpired(false)//是否過期.accountLocked(false).roles("ADMIN").build();}}
}
1.3、用戶-角色-權限-資源
RBAC(Role-Based Access Control,基于角色的訪問控制)是一種常用的數據設計方案,它將用戶的權限分配和管理與角色相關聯。以下是一個基本的RBAC數據庫設計方案的示例:
1、用戶表(User table):包含用戶的基本信息,例如用戶名、密碼和其他身份驗證信息。
列名 | 數據類型 | 描述 |
---|---|---|
user_id | int | 用戶ID |
username | varchar | 用戶名 |
password | varchar | 密碼 |
varchar | 電子郵件 | |
… | … | … |
2、角色表(Role table):儲存所有可能得角色及其描述。
列名 | 數據類型 | 描述 |
---|---|---|
role_id | int | 角色ID |
role_name | varchar | 角色名稱 |
description | varchar | 角色描述 |
… | … | … |
3、權限表(Permission table):定義系統中所有可能得權限
列名 | 數據類型 | 描述 |
---|---|---|
permission_id | int | 權限ID |
permission_name | varchar | 權限名稱 |
description | varchar | 角色描述 |
… | … | … |
4、用戶角色關聯表(User-Role table):將用戶與角色關聯起來。
列名 | 數據類型 | 描述 |
---|---|---|
user_role_id | int | 用戶角色關聯ID |
user_id | int | 用戶ID |
role_id | int | 角色ID |
… | … | … |
5、角色權限關聯表(Role-Permission table):將角色與權限關聯起來。
列名 | 數據類型 | 描述 |
---|---|---|
role_permission_id | int | 用戶角色關聯ID |
role_id | int | 角色ID |
permission_id | int | 權限ID |
… | … | … |
在這個設計方案中,用戶可以被分配一個或多個角色,而每個角色又可以具有一個或多個權限。通過對用戶角色關聯和角色權限關聯表進行操作,可以實現靈活的權限管理和訪問控制。
2、基于方法的授權
2.1、開啟方法授權
在配置文件中添加@EnableMethodSecurity注解,并修改authorizeHttpRequests
@Configuration //配置類
@EnableMethodSecurity
public class WebSecurityConfig {...http.authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated());
}
2.2、給用戶授予角色和權限
DBUserDetailsManager中的loadUserByUsername方法:
return org.springframework.security.core.userdetails.User.withUsername(user.getUsername()).password(user.getPassword()).disabled(!user.getEnabled())//用戶是否禁用.credentialsExpired(false)//是否過期.accountLocked(false).roles("ADMIN")//authorities和roles不能同時使用會覆蓋.authorities("USER_ADD","USER_LIST").build();}
2.3、常用授權注解
@GetMapping(path = "/list")@PreAuthorize("hasRole('ADMIN') and authentication.name == 'abc'")public List<User> getList(){return userService.list();}@PreAuthorize("hasAuthority('USER_ADD')")@PostMapping(path = "/add")public void add(@RequestBody User user){userService.saveUserDetails(user);}