# fast-security **Repository Path**: zxyd/fast-security ## Basic Information - **Project Name**: fast-security - **Description**: 基于 Spring Security 的快速使用框架。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2023-11-17 - **Last Updated**: 2023-11-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 项目说明 本项目完全基于 `Spring Security`,只针对日常开发项目中的认证、动态权限需求做一层封装,干净纯洁。 可用于项目快速开发、`Spring Security` 框架学习。 另鉴于 JWT 目前用的最多,内置封装逻辑为,认证成功后生成 token 返回。 token 中包含 userId、roleIds。 Token 内容示例: ``` { alg: "HS256" }. { roles: "10,1,5", exp: 1626480624, userId: "1" }. [signature] ``` ## 包说明 ``` ├─authentication 鉴权相关处理 ├─authorization 认证相关处理 ├─config Security配置 ├─constant 常量 ├─filter 全局过滤器(登录入口、JWT 处理入口) ├─handle 认证、鉴权结果处理器 ├─loginlogic 登录逻辑 │ └─base ├─model 实体 └─utils 工具类 ``` ## 快速使用 1. 引入依赖 此包未发布到中央仓库,请自行安装至本地仓库。 ```xml pri.damai fast-security 0.0.1-SNAPSHOT ``` 2. 提供用户查询接口。 ```java @Component public class UserServiceImpl{ static List userList = new ArrayList<>(); static { FastUserInfo one = new FastUserInfo(); one.setId("1"); one.setPhone("123456"); one.setUsername("xxx"); one.setPassword("xxxx"); ArrayList oneRoles = new ArrayList<>(); oneRoles.add("10"); one.setRoleList(oneRoles); FastUserInfo two = new FastUserInfo(); two.setId("2"); two.setPhone("54321"); two.setUsername("yyyy"); two.setPassword("xxxx"); ArrayList twoRoles = new ArrayList<>(); twoRoles.add("5"); two.setRoleList(twoRoles); FastUserInfo three = new FastUserInfo(); three.setId("3"); three.setPhone("0997876"); three.setUsername("bbbb"); three.setPassword("xxxx"); ArrayList threeRoles = new ArrayList<>(); threeRoles.add("1"); three.setRoleList(threeRoles); userList.add(one); userList.add(two); userList.add(three); } public FastUserInfo loadUserByPhone(String phone) { return userList.stream() .filter(user -> user.getPhone().equals(phone)) .findAny() .orElseThrow(() -> new AuthenticationServiceException("无此用户")); } } ``` 3. 实现登录逻辑 ```java @Component public class PhoneLogin extends AbstractLoginLogic { @Resource UserServiceImpl userService; @Override public String getSupportLoginType() { return "phone"; } @Override public void checkParam(LoginData loginData) throws AuthenticationException { String msg = null; if (loginData.getPhone() == null) { msg = "手机号不可为空"; } if (loginData.getPhoneVerifyCode() == null) { msg = msg + ", 短信验证码不可为空"; } if (!Objects.equals(msg, null)) { this.throwException(msg); } } @Override protected void login(LoginData loginData) throws AuthenticationException { if (!"22".equals(loginData.getPhoneVerifyCode())) { this.throwException("验证码错误"); } // 具体登录逻辑 FastUserInfo fastUserInfo = this.getUserDetails(loginData); } @Override public FastUserInfo getUserDetails(LoginData loginData) { return userService.loadUserByPhone(loginData.getPhone()); } private void throwException(String msg) { throw new AuthenticationServiceException(msg); } } ``` 4. 实现 `ResourceService` 接口 。通过此接口,提供权限查询功能。 ```java @Component public class MyResourceImpl implements ResourceService { static HashMap> roleMap = new HashMap<>(); static { String superAdmin = "10"; String admin = "5"; String user = "1"; ArrayList superAdminUrlRoleIds = new ArrayList<>(); superAdminUrlRoleIds.add(superAdmin); superAdminUrlRoleIds.add(admin); superAdminUrlRoleIds.add(user); roleMap.put("/superAdmin", superAdminUrlRoleIds); ArrayList adminUrlRoleIds = new ArrayList<>(); adminUrlRoleIds.add(admin); adminUrlRoleIds.add(user); roleMap.put("/admin", adminUrlRoleIds); ArrayList userUrlRoleIds = new ArrayList<>(); userUrlRoleIds.add(admin); userUrlRoleIds.add(user); roleMap.put("/user", userUrlRoleIds); } @Override public List getRolesByUrl(String url) { return roleMap.get(url); } } ``` ## 其他扩展功能 ### 可选 yml 配置 以下配置均有默认值,有指定要求时再配置即可。 ```yaml fast-security: not-login-urls: # 指定无需登录即可访问的接口 - /user login-url: # 指定登录接口的url expiration: # 指定 token 过期时间 jwt-secret: # 指定 Jwt 密匙 authentication-failed-code: # 指定登录失败错误码 unauthorized-code: # 指定未认证错误码 permission-denied-code: # 指定未授权错误码 no-roles-pass: # 未配置Url时,是否直接放行 ``` ### 登录成功处理器 在实际开发中,我们可能需要存储 token。可实现 `LoginSuccessResultHandler` 接口来自定义功能。 ```java @Component public class GGLoginSuccessResultHandler implements LoginSuccessResultHandler { @Override public Object handleResult(UserDetails userDetails, String token) { // 保存 token or 其他操作 return null; } } ``` ### 自定义登录失败处理器 ```java @Component public class GGLoginFailureResultHandler implements LoginFailureResultHandler { @Override public Object handleResult(AuthenticationException e) { return null; } } ``` ## 总体流程说明 ### 首次登录流程 ```mermaid graph TD A(登录请求) --> B(MyAuthenticationProcessingFilter) --> C(MyAuthenticationTokenProvider) --> D{AbstractLoginLogic} D --> |无异常| D1(MyAuthenticationSuccessHandler) --> D2(LoginSuccessResultHandler) --> D3[登录成功] D --> |有异常| D4(MyAuthenticationFailureHandler) --> D5(LoginFailureResultHandler) --> D6[登录失败] ``` ### 业务请求 ```mermaid graph TD A(业务请求) --> B(JwtFilter) --> C(MySecurityMetadataSource) --> D(MyAccessDecisionManager) --> E{异常} E --> |有异常| E1[业务请求失败, 无权访问] E --> |无异常| E2(鉴权成功) --> E3[处理业务] ```