opcooc / UMS

User management scaffolding, integration: validate code, mobile login, OAuth2(automatic registration, binding and unbinding), RBAC-based uri access control function, routing function of multiple callback addresses through a unified callback address entry, and sign etc...

Home Page:https://github.com/ZeroOrInfinity/UMS/wiki

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

UMS (user manage scaffolding) 用户管理脚手架:

JDK Maven MySQL Redis SpringBoot SpringSecurity SpringSession license

用户管理脚手架集成:用户密码登录、手机登录、支持 JustAuth 支持的所有第三方授权登录、验证码、基于 RBAC 的 uri 访问权限控制功能、签到等功能. 通过配置文件与实现 用户服务, 短信发送服务, 获取角色权限服务 三个 API 接口就可以实现上述功能,实现快速开发,只需要专注于业务逻辑.

User management scaffolding, integration: User password login, mobile login, Support all third-party authorized logins supported by JustAuth, validate code, RBAC-based uri access control function, sign etc...

ums-arch

一、UMS 功能列表(UMS feature list)

  • 验证码(图片,短信, 滑块)校验功能(validate code(image, SMS, slider) verification function).
  • 手机登录功能,登录后自动注册(Mobile login function, automatic registration after login).
  • 支持所有 JustAuth 支持的第三方授权登录,登录后自动注册 或 绑定 或 创建临时用户([TemporaryUser](https://github.com/ZeroOrInfinity/UMS/blob/master /src/main/java/top/dcenter/ums/security/core/oauth/userdetails/TemporaryUser.java))(OAuth2 login and auto signUp and auto binding).
    • 支持定时刷新 accessToken, 支持分布式定时任务(Support timing refresh accessToken, support distributed timing tasks).
    • 支持第三方授权登录的用户信息表与 token 信息表的缓存功能(Support the caching function of user table and token table by OAuth2 login).
    • 支持第三方绑定(binding)与解绑(unbinding)及查询接口(top.dcenter.ums.security.core.oauth.repository.UsersConnectionRepository).
  • 访问权限控制功能, 支持多租户(Access control function, support multi tenancy).
  • 简化 session、remember me、csrf 等配置(Simplify session、remember me、csrf etc configuration).
  • 根据设置的响应方式(JSON 与 REDIRECT)返回 json 或 html 数据.
  • 签到功能(sign).
  • 支持基于 SLF4J MDC 机制的日志链路追踪功能.

模块功能

模块 功能
commons 通用组件模块
core 验证码/用户名密码登录/手机登录且自动注册/OAuth2 login by JustAuth/访问权限控制/签到/简化HttpSecurity(session、remember me、csrf 等)配置/session redis 缓存/可配置的响应方式(JSON 与 REDIRECT)返回 json 或 html 数据
demo basic-example/basic-detail-example/permission-example/quickStart/session-detail-example/validate-codi-example/justAuth-security-oauth2-example

demo 演示功能

demo 演示功能
basic-example core 模块基本功能: 最简单的配置
basic-detail-example core 模块基本功能详细的配置: 含anonymous/session简单配置/rememberMe/csrf/登录路由/签到, 不包含session详细配置/验证码/手机登录/权限.
permission-example core 模块: 基于 RBAC 的权限功能设置
quickStart 快速开始示例
justAuth-security-oauth2-example 第三方授权登录详细示例, MDC 日志链路追踪配置
session-detail-example core 模块: session 与 session 缓存详细配置
validate-code-example core 模块基本功能: 验证码(含自定义滑块验证码), 手机登录配置

微信群:UMS 添加微信(z56133)备注(UMS)

二、maven

<dependency>
    <groupId>top.dcenter</groupId>
    <artifactId>ums-core-spring-boot-starter</artifactId>
    <version>latest</version>
</dependency>

三、TODO List:

    1. 准备基于 spring-security5.4 添加 JWT, OAuth2 authenticate server

四、快速开始(Quick Start)


五、接口使用说明(Interface instructions):

实现对应功能时需要实现的接口(The interface that needs to be implemented when the corresponding function is present):

  1. 用户服务(user service): 必须实现(Must implemente)

  2. 图片验证码(image validate code): 已实现缓存功能, 支持定时刷新缓存功能, 可以自定义缓存验证码图片的输出路径与缓存数量

  3. 短信验证码(SMS validate code): 默认空实现

  4. 滑块验证码(Slider validate code): 已实现缓存功能, 支持定时刷新缓存功能, 可以自定义缓存验证码图片的输出路径与缓存数量, 支持自定义源图片路径与模板图片路径

  5. 自定义验证码(customize validate code):

  6. 访问权限控制功能(Access control function): 基于 RBAC 的访问权限控制: 支持多租户与SCOPE

    • UriAuthorizeService: 推荐通过实现 AbstractUriAuthorizeService 来实现此接口

    • AbstractUriAuthorizeService: 必须实现(Must implemente)

      • uri(资源) 访问权限控制服务接口抽象类, 定义了基于(角色/多租户/SCOPE)的访问权限控制逻辑. 实现 AbstractUriAuthorizeService 抽象类并注入 IOC 容器即可替换 DefaultUriAuthorizeService.

      • 注意:

        1. 推荐实现 AbstractUriAuthorizeService 同时实现 UpdateAndCacheAuthoritiesService 更新与缓存权限服务, 有助于提高授权服务性能.

        2. 对传入的 Authentication 的 authorities 硬性要求:

         // 此 authorities 可以包含:  [ROLE_A, ROLE_B, ROLE_xxx TENANT_110110, SCOPE_read, SCOPE_write, SCOPE_xxx]
         // 如上所示:
         //    1. 角色数量    >= 1
         //    2. SCOPE 数量 >= 0
         //    3. 多租户数量  = 1 或 0
         Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();

        3. 此框架默认实现 hasPermission(Authentication, HttpServletRequest) 方法访问权限控制, 通过 UriAuthoritiesPermissionEvaluator 实现, 使用此接口的前提条件是: 应用使用的是 restful 风格的 API; 如果不是 restful 风格的 API, 请使用 hasPermission(Authentication, String, String) 接口的访问权限控制, 此接口使用注解的方式 @PerAuthorize("hasPermission('/users', 'list')") 来实现, 使用注解需先开启 @EnableGlobalMethodSecurity(prePostEnabled = true) 注解.

    • UpdateAndCacheAuthoritiesService:

      • 用于更新或缓存基于(角色/多租户/SCOPE)角色的权限的服务接口, 每次更新角色的 uri(资源)权限时,需要调用此接口, 推荐实现此 RolePermissionsService 接口, 会自动通过 AOP 方式实现发布 UpdateRolesAuthoritiesEvent 事件, 从而调用 UpdateAndCacheAuthoritiesService 对应的方法.

      • 建议:

        1. 基于 角色 的权限控制: 实现所有角色 uri(资源) 的权限 Map(role, map(uri, Set(permission))) 的更新与缓存本机内存.

        2. 基于 SCOPE 的权限控制: 情况复杂一点, 但 SCOPE 类型比较少, 也还可以像 1 的方式实现缓存本机内存与更新.

        3. 基于 多租户 的权限控制: 情况比较复杂, 租户很少的情况下, 也还可以全部缓存在本机内存, 通常情况下全部缓存内存不现实, 只能借助于类似 redis 等的内存缓存.

    • RolePermissionsService:

      • 更新与查询基于(角色/多租户/SCOPE)的角色资源服务接口. 主要用于给角色添加权限的操作.

      • 注意:

        1. 在添加资源时, 通过PermissionType.getPermission() 来规范的权限格式, 因为要支持 restful 风格的 Api, 在授权时需要对 HttpMethod 与对应的权限进行匹配判断

        2. 如果实现了 UpdateAndCacheAuthoritiesService 接口, 未实现 RolePermissionsService 接口, 修改或添加基于"角色/多租户/SCOPE "的资源权限时一定要调用 UpdateAndCacheAuthoritiesService 对应的方法, 有两种方式: 一种发布事件, 另一种是直接调用对应服务;

        // 1. 推荐用发布事件(异步执行)
        applicationContext.publishEvent(new UpdateRolesAuthoritiesEvent(true, ResourcesType.ROLE));
        applicationContext.publishEvent(new UpdateRolesAuthoritiesEvent(true, ResourcesType.TENANT));
        applicationContext.publishEvent(new UpdateRolesAuthoritiesEvent(true, ResourcesType.SCOPE));
        // 2. 直接调用服务
        // 基于角色
        UpdateAndCacheAuthoritiesService.updateAuthoritiesOfAllRoles();
        // 基于多租户
        UpdateAndCacheAuthoritiesService.updateAuthoritiesOfAllTenant();
        // 基于 SCOPE
        UpdateAndCacheAuthoritiesService.updateAuthoritiesOfAllScopes();

        3. 实现此 RolePermissionsService 接口, 不需要执行上两种方法的操作, 已通过 AOP 方式实现发布 UpdateRolesAuthoritiesEvent 事件.

  7. Auth2StateCoder: 用户需要时实现, 对第三方授权登录流程中的 state 进行自定义编解码. 可以传递必要的信息, 如: 第三方登录成功的跳转地址等 注意此接口的两个方法必须同时实现对应的编解码逻辑, 实现此接口后注入 IOC 容器即可, 如有前端向后端获取 authorizeUrl 时向后端传递额外参数 且用作注册时的信息, 需配合 UmsUserDetailsService.registerUser(AuthUser, String, String, String) 方法实现.

  8. Auth2UserService: 获取第三方用户信息的接口, 一般不需要用户实现, 除非想自定义获取第三方用户信息的逻辑, 实现此接口注入 IOC 容器即可替代.

  9. UsersConnectionRepository: 第三方授权登录的第三方用户信息增删改查, 绑定与解绑及查询是否绑定与解绑接口, 一般不需要用户实现. 除非想自定义获取第三方用户信息的逻辑, 实现此接口注入 IOC 容器即可替代.

  10. UsersConnectionTokenRepository: 第三方授权登录用户 accessToken 信息表增删改查接口, 一般不需要用户实现. 除非想自定义获取第三方用户信息的逻辑, 实现此接口注入 IOC 容器即可替代.

  11. ConnectionService: 第三方授权登录用户的注册, 绑定, 更新第三方用户信息与 accessToken 信息的接口, 一般不需要用户实现. 除非想自定义获取第三方用户信息的逻辑, 实现此接口注入 IOC 容器即可替代.


六、Configurations:

功能(Features) 模块(model) demo模块--简单配置(Simple Configuration) demo模块--详细配置(detail Configuration)
1. 基本功能 core basic-example
2. 登录路由功能 core basic-detail-example
3. session core session-detail-example
4. remember-me core basic-detail-example
5. csrf core basic-detail-example
6. anonymous core basic-detail-example
7. 验证码 core validate-code-example
8. 手机登录 core basic-detail-example
9. 第三方登录 core basic-detail-example
10. 给第三方登录时用的数据库表 user_connection 与 auth_token 添加 redis cache core basic-detail-example
11. 签到 core basic-detail-example
12. 基于 RBAC 的访问权限控制功能 core permission-example
13. 线程池配置 core justAuth-security-oauth2-example
14. 基于 SLF4J MDC 机制的日志链路追踪配置 core justAuth-security-oauth2-example

1. HttpSecurity 配置问题:UMS 中的 HttpSecurityAware 配置与应用中的 HttpSecurity 配置冲突问题:

  1. 如果是新建应用添加 HttpSecurity 配置, 通过下面的接口即可:
  2. 如果是已存在的应用:
    • 添加 HttpSecurity 配置, 通过下面的接口即可: HttpSecurityAware
    • 已有的 HttpSecurity 配置, 让原有的 HttpSecurity 配置实现此接口进行配置: top.dcenter.security.core.api.config.HttpSecurityAware

2. 在 ServletContext 中存储的属性:

  • 属性名称: SecurityConstants.SERVLET_CONTEXT_PERMIT_ALL_SET_KEY
  • 属性值: Set, 把权限类型为 PERMIT_ALL 的 Set 存储在 servletContext .

3. servletContextPath 的值存储在 MvcUtil.servletContextPath :

  • 通过静态方法获取 MvcUtil.getServletContextPath()
  • MvcUtil.servletContextPath 的值是通过: SecurityAutoConfiguration#afterPropertiesSet() 接口注入

4. 验证码优先级(Verification code Priority):

  • 同一个 uri 由多种验证码同时配置, 优先级如下: SMS > CUSTOMIZE > SELECTION > TRACK > SLIDER > IMAGE

5. Jackson 序列化与反序列化

// 示例
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
// Auth2Jackson2Module 为此项目实现的反序列化配置     
objectMapper.registerModules(new CoreJackson2Module(), new WebJackson2Module(), new Auth2Jackson2Module());
jackson2JsonRedisSerializer.setObjectMapper(om);
  • 注意: UmsUserDetailsService 的注册用户方法返回的 UserDetails 的默认实现 User 已实现反序列化器, 如果是开发者自定义的子类, 需开发者自己实现反序列化器.

属性配置列表(Properties Configurations)
基本属性(Basic Properties)
签到属性(Sign Properties)
手机登录属性(Mobile login Properties)
验证码属性(Validate Code Properties)
第三方授权登录(OAuth2 JustAuth)
线程池属性(ThreadPool Properties)
基于 SLF4J MDC 机制的日志链路追踪属性
第三方授权登录用户信息数据 redis 缓存配置(UserConnection Redis cache Properties)
第三方授权登录用户信息表 user_connection sql 配置(UserConnection sql Properties)

九、参与贡献(Participate in contribution)

  1. Fork 本项目
  2. 新建 Feat_xxx 分支
  3. 提交代码
  4. 新建 Pull Request

十、流程图(Flow chart): 随着版本迭代会有出入

1. 滑块验证码(sliderValidateCode)

sliderValidateCode


十一、时序图(Sequence Diagram): 随着版本迭代会有出入

时序图
csrf
获取验证码逻辑
图片验证码逻辑
logout
第三方授权登录
rememberMe
核心配置逻辑
登录路由
session
手机登录
过时:第三方绑定与解绑
过时:第三方授权登录
过时:第三方授权登录注册

十二、基于 SLF4J MDC 机制的日志链路追踪功能

  • 使用此功能在日志配置文件中的 pattern 中添加 %X{MDC_TRACE_ID} 即可.
<!-- 控制台 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <!-- 日志格式 -->
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level ${PID:- } --- [%thread] %X{MDC_TRACE_ID} %logger[%L] - %msg%n</pattern>
        <charset>utf-8</charset>
    </encoder>
    <!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <!-- 只有这个日志权限才能看,sql语句 -->
        <level>DEBUG</level>
    </filter>
</appender>
  • 多线程使用问题: 父线程新建子线程之前调用 MDC.getCopyOfContextMap() 方法获取 MDC context, 子线程在执行操作前先调用 MDC.setContextMap(context) 方法将父线程的 MDC context 设置到子线程中. ThreadPoolTaskExecutor 的配置请参考 ScheduleAutoConfiguration.
  • 多线程传递 MDC context 简单示例:
final Logger log = LoggerFactory.getLogger(this.getClass());
// 获取父线程 MDC 中的内容
final Map<String, String> context = MDC.getCopyOfContextMap();
final Runnable r = () -> {
    log.info("testMDC");
    System.out.println("...");
};
new Thread(() -> {
    // 将父线程的 MDC context 设置到子线程中
    MDC.setContextMap(context);
    r.run();
}, "testMDC").start();

About

User management scaffolding, integration: validate code, mobile login, OAuth2(automatic registration, binding and unbinding), RBAC-based uri access control function, routing function of multiple callback addresses through a unified callback address entry, and sign etc...

https://github.com/ZeroOrInfinity/UMS/wiki

License:MIT License


Languages

Language:Java 99.9%Language:HTML 0.1%