10 Star 66 Fork 6

要懂得舍得 / UMS

Create your Gitee Account
Explore and code with more than 5 million developers,Free private repositories !:)
Sign up
Clone or download
Cancel
Notice: Creating folder will generate an empty file .keep, because not support in Git
Loading...
Readme.osc.md

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

JDK Maven MySQL Redis SpringBoot SpringSecurity SpringSession JustAuth license

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

ums-arch

一、UMS 功能列表

  • 验证码(图片,短信, 滑块)校验功能。
  • 手机登录功能,登录后自动注册。
  • 支持所有 JustAuth 支持的第三方授权登录,登录后自动注册或绑定或创建临时用户(TemporaryUser)。
    • 支持定时刷新 accessToken, 支持分布式定时任务。
    • 支持第三方授权登录的用户信息表与 token 信息表的缓存功能。
    • 支持第三方绑定与解绑及查询接口(top.dcenter.ums.security.core.oauth.repository.UsersConnectionRepository).
  • 访问权限控制功能, 支持多租户。
  • 简化 session、remember me、csrf 等配置。
  • 根据设置的响应方式(JSON 与 REDIRECT)返回 json 或 html 数据。
  • 签到功能。
  • 支持基于 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 模块基本功能: 验证码(含自定义滑块验证码), 手机登录配置

Github 更新日志(UpdatedLog) | Gitee 更新日志

Gitee文档地址 | Github 文档地址

微信群: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
    1. 添加多租户注册功能与接口

四、快速开始


五、接口使用说明:

实现对应功能时需要实现的接口:

  1. 用户服务: 必须实现

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

  3. 短信验证码: 默认空实现

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

  5. 自定义验证码:

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

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

    • AbstractUriAuthorizeService: 必须实现

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

      • 注意:

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

        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) 注解.

    • UpdateAndCacheRolesResourcesService:

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

      • 建议:

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

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

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

    • RolePermissionsService:

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

      • 注意:

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

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

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

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

        4. 注意: RolePermissionsServiceAspect 切面生效前提, 事务的 Order 的值必须 大于 1, 如果是默认事务(优先级为 Integer.MAX_VALUE )不必关心这个值, 如果是自定义事务, 且设置了 Order 的值, 那么值必须 大于 1.

    • 时序图

授权逻辑时序图

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

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

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

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

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


六、Configurations:

功能 模块 demo模块--简单配置 demo模块--详细配置
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. 验证码优先级:

  • 同一个 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 已实现反序列化器, 如果是开发者自定义的子类, 需开发者自己实现反序列化器.

八、属性配置列表

属性配置列表
基本属性
签到属性
手机登录属性
验证码属性
第三方授权登录
线程池属性
基于 SLF4J MDC 机制的日志链路追踪属性
第三方授权登录用户信息数据 redis 缓存配置
第三方授权登录用户信息表 user_connection sql 配置

九、参与贡献

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

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

1. 滑块验证码(sliderValidateCode)

sliderValidateCode


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

时序图
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();

Comments ( 4 )

Sign in for post a comment

About

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

Releases (18)

All

Gitee Metrics

Contributors

All

Activities

load more
can not load any more
Java
1
https://gitee.com/pcore/UMS.git
git@gitee.com:pcore/UMS.git
pcore
UMS
UMS
master

Search