Browse Source

同步器增加属性映射管理

llh 9 months ago
parent
commit
e5a2210d90
100 changed files with 1747 additions and 844 deletions
  1. 32 7
      README.md
  2. 32 7
      README_en.md
  3. 32 7
      README_zh.md
  4. 28 1
      ReleaseNotes.txt
  5. 12 12
      build_cnf.gradle
  6. 63 144
      config/build_standard.gradle
  7. 148 64
      config/build_tradition.gradle
  8. 6 6
      gradle.properties
  9. 1 1
      gradle/wrapper/gradle-wrapper.properties
  10. 1 1
      maxkey-authentications/maxkey-authentication-core/build.gradle
  11. 59 0
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/QrCodeCredentialDto.java
  12. 61 0
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/ScanCode.java
  13. 1 1
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/SignPrincipal.java
  14. 3 2
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/jwt/AuthJwtService.java
  15. 1 1
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/InMemorySessionManager.java
  16. 1 1
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/RedisSessionManager.java
  17. 11 11
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/SessionManager.java
  18. 2 2
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/SessionManagerFactory.java
  19. 12 5
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/web/AuthTokenRefreshPoint.java
  20. 32 23
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/web/AuthorizationUtils.java
  21. 1 1
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/web/CurrentUserMethodArgumentResolver.java
  22. 5 6
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/web/FileUploadEndpoint.java
  23. 9 10
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/web/InstitutionEndpoint.java
  24. 1 1
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/autoconfigure/MvcCurrentUserAutoConfiguration.java
  25. 3 3
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/autoconfigure/SessionAutoConfiguration.java
  26. 2 2
      maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/autoconfigure/TokenAutoConfiguration.java
  27. 3 0
      maxkey-authentications/maxkey-authentication-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  28. 5 3
      maxkey-authentications/maxkey-authentication-provider/build.gradle
  29. 59 50
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/AbstractAuthenticationProvider.java
  30. 130 0
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/impl/AppAuthenticationProvider.java
  31. 3 5
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/impl/MfaAuthenticationProvider.java
  32. 1 1
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/impl/MobileAuthenticationProvider.java
  33. 5 12
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/impl/NormalAuthenticationProvider.java
  34. 104 0
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/impl/ScanCodeAuthenticationProvider.java
  35. 1 1
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/impl/TrustedAuthenticationProvider.java
  36. 123 0
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/scancode/ScanCodeService.java
  37. 70 0
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/scancode/ScanCodeState.java
  38. 36 0
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/scancode/ScancodeSignInfo.java
  39. 3 3
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/realm/AbstractAuthenticationRealm.java
  40. 3 3
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/realm/jdbc/JdbcAuthenticationRealm.java
  41. 1 1
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/realm/ldap/ActiveDirectoryServer.java
  42. 2 2
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/realm/ldap/LdapAuthenticationRealm.java
  43. 6 6
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/realm/ldap/LdapAuthenticationRealmService.java
  44. 1 1
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/realm/ldap/StandardLdapServer.java
  45. 7 6
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/support/jwt/HttpJwtEntryPoint.java
  46. 1 1
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/support/rememberme/AbstractRemeberMeManager.java
  47. 2 1
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/support/wsfederation/HttpWsFederationEntryPoint.java
  48. 1 1
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/support/wsfederation/WsFederationServiceImpl.java
  49. 47 19
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/autoconfigure/AuthnProviderAutoConfiguration.java
  50. 6 6
      maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/autoconfigure/JwtAuthnAutoConfiguration.java
  51. 2 0
      maxkey-authentications/maxkey-authentication-provider/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  52. 1 1
      maxkey-authentications/maxkey-authentication-social/src/main/java/me/zhyd/oauth/request/AuthWeChatEnterpriseWebRequestCost.java
  53. 1 1
      maxkey-authentications/maxkey-authentication-social/src/main/java/org/dromara/maxkey/authn/support/socialsignon/AbstractSocialSignOnEndpoint.java
  54. 26 26
      maxkey-authentications/maxkey-authentication-social/src/main/java/org/dromara/maxkey/authn/support/socialsignon/SocialSignOnEndpoint.java
  55. 1 0
      maxkey-authentications/maxkey-authentication-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
  56. 3 2
      maxkey-common/build.gradle
  57. 40 0
      maxkey-common/src/main/java/org/dromara/maxkey/adapter/LocalDateTimeAdapter.java
  58. 2 1
      maxkey-common/src/main/java/org/dromara/maxkey/crypto/ReciprocalUtils.java
  59. 1 1
      maxkey-common/src/main/java/org/dromara/maxkey/crypto/jwt/HMAC512Service.java
  60. 1 1
      maxkey-common/src/main/java/org/dromara/maxkey/crypto/jwt/encryption/service/impl/RecipientJwtEncryptionAndDecryptionServiceBuilder.java
  61. 1 1
      maxkey-common/src/main/java/org/dromara/maxkey/crypto/jwt/signer/service/impl/DefaultJwtSigningAndValidationService.java
  62. 1 1
      maxkey-common/src/main/java/org/dromara/maxkey/crypto/jwt/signer/service/impl/SymmetricSigningAndValidationServiceBuilder.java
  63. 7 7
      maxkey-common/src/main/java/org/dromara/maxkey/entity/Message.java
  64. 1 1
      maxkey-common/src/main/java/org/dromara/maxkey/pretty/Pretty.java
  65. 2 7
      maxkey-common/src/main/java/org/dromara/maxkey/util/AuthorizationHeaderUtils.java
  66. 32 32
      maxkey-common/src/main/java/org/dromara/maxkey/util/DateUtils.java
  67. 1 1
      maxkey-common/src/main/java/org/dromara/maxkey/util/EthernetAddress.java
  68. 1 0
      maxkey-common/src/main/java/org/dromara/maxkey/util/PathUtils.java
  69. 42 42
      maxkey-common/src/main/java/org/dromara/maxkey/util/QRCodeUtils.java
  70. 10 10
      maxkey-common/src/main/java/org/dromara/maxkey/util/SnowFlakeId.java
  71. 6 4
      maxkey-common/src/main/java/org/dromara/maxkey/util/StrUtils.java
  72. 54 0
      maxkey-common/src/main/java/org/dromara/maxkey/util/TimeJsonUtils.java
  73. 0 1
      maxkey-core/src/main/java/org/dromara/maxkey/configuration/ApplicationConfig.java
  74. 5 5
      maxkey-core/src/main/java/org/dromara/maxkey/entity/Access.java
  75. 1 0
      maxkey-core/src/main/java/org/dromara/maxkey/entity/Accounts.java
  76. 1 0
      maxkey-core/src/main/java/org/dromara/maxkey/entity/ChangePassword.java
  77. 1 2
      maxkey-core/src/main/java/org/dromara/maxkey/entity/FileUpload.java
  78. 0 14
      maxkey-core/src/main/java/org/dromara/maxkey/entity/Institutions.java
  79. 0 142
      maxkey-core/src/main/java/org/dromara/maxkey/entity/Localization.java
  80. 0 6
      maxkey-core/src/main/java/org/dromara/maxkey/entity/Saml20Metadata.java
  81. 4 4
      maxkey-core/src/main/java/org/dromara/maxkey/entity/cnf/CnfEmailSenders.java
  82. 4 4
      maxkey-core/src/main/java/org/dromara/maxkey/entity/cnf/CnfLdapContext.java
  83. 3 3
      maxkey-core/src/main/java/org/dromara/maxkey/entity/cnf/CnfPasswordPolicy.java
  84. 4 4
      maxkey-core/src/main/java/org/dromara/maxkey/entity/cnf/CnfSmsProvider.java
  85. 6 2
      maxkey-core/src/main/java/org/dromara/maxkey/entity/dto/TimeBasedDto.java
  86. 1 1
      maxkey-core/src/main/java/org/dromara/maxkey/entity/history/HistoryConnector.java
  87. 1 1
      maxkey-core/src/main/java/org/dromara/maxkey/entity/history/HistoryLogin.java
  88. 1 1
      maxkey-core/src/main/java/org/dromara/maxkey/entity/history/HistoryLoginApps.java
  89. 1 1
      maxkey-core/src/main/java/org/dromara/maxkey/entity/history/HistorySynchronizer.java
  90. 1 1
      maxkey-core/src/main/java/org/dromara/maxkey/entity/history/HistorySystemLogs.java
  91. 1 1
      maxkey-core/src/main/java/org/dromara/maxkey/entity/idm/GroupMember.java
  92. 1 25
      maxkey-core/src/main/java/org/dromara/maxkey/entity/idm/Groups.java
  93. 1 1
      maxkey-core/src/main/java/org/dromara/maxkey/entity/idm/Organizations.java
  94. 12 7
      maxkey-core/src/main/java/org/dromara/maxkey/entity/idm/UserInfo.java
  95. 6 6
      maxkey-core/src/main/java/org/dromara/maxkey/entity/permissions/Permission.java
  96. 185 0
      maxkey-core/src/main/java/org/dromara/maxkey/entity/permissions/PermissionRole.java
  97. 1 1
      maxkey-core/src/main/java/org/dromara/maxkey/entity/permissions/Resources.java
  98. 13 4
      maxkey-core/src/main/java/org/dromara/maxkey/entity/permissions/RoleMember.java
  99. 14 27
      maxkey-core/src/main/java/org/dromara/maxkey/entity/permissions/Roles.java
  100. 64 0
      maxkey-core/src/main/java/org/dromara/maxkey/exception/BusinessException.java

+ 32 - 7
README.md

@@ -38,7 +38,7 @@ QQ : <b> 1054466084 </b>
 
 email: <b> support@maxsso.net </b>
 
-Code Hosting <a href="https://github.com/dromara/MaxKey" target="_blank"><b>GitHub</b></a> | <a href="https://gitee.com/dromara/MaxKey" target="_blank"><b>Gitee</b></a>
+Code Hosting <a href="https://github.com/dromara/MaxKey" target="_blank"><b>GitHub</b></a> | <a href="https://gitee.com/dromara/MaxKey" target="_blank"><b>Gitee</b></a>  | <a href="https://gitcode.com/dromara/MaxKey/overview" target="_blank"><b>GitCode</b></a>
 
 ><b> Single Sign On </b>(<b> SSO </b >),Users only need to login to the authentication center once , access all the trusted application systems without logging in again.
 >
@@ -120,7 +120,7 @@ App Management UI
 
 | Version    | Date   |  Download URL  |
 | --------   | :----- | :----           | 
-| v 4.0.5   | 2024/06/27   | <a href="https://www.maxkey.top/zh/about/download.html"  target="_blank">Download</a> |
+| v 4.1.1   | 2024/08/20   | <a href="https://www.maxkey.top/zh/about/download.html"  target="_blank">Download</a> |
 
 # Install
 
@@ -169,12 +169,15 @@ App Management UI
 | 单位    |
 | :-----  |
 | 中国人民警察大学                            |
+| 福耀科技大学                                |
 | 兰州现代职业学院                            |
 | 长春职业技术学院                            |
 | 云南师范大学                                |
 | 云南农业职业技术学院                        |
 | 惠州卫生职业技术学院                        |
+| 厦门软件职业技术学院                        |
 | 宜昌市三峡中等专业学校                      |
+| 上海图书馆                                  |
 | 重庆市北碚图书馆                            |
 | 天津市劳动保障技师学院                      |
 | 南京财经高等职业技术学校                    |
@@ -182,6 +185,7 @@ App Management UI
 | 余姚市教育局                                |
 | 中国金融认证中心                            |
 | 国家高端智能化家用电器创新中心              |
+| 国家中小企业数字化转型促进中心              |
 | 国元证券                                    |
 | 华夏金融租赁有限公司                        |
 | 国宝人寿保险股份有限公司                    |
@@ -195,6 +199,7 @@ App Management UI
 | 百度智能云身份管理服务                      |
 | 360公司                                     |
 | 三一华兴                                    |
+| 云小厨CloudKitchens                         |
 | 西藏阜康医院                                |
 | 海阳市人民医院                              |
 | 上海逸广信息科技有限公司                    |
@@ -202,7 +207,10 @@ App Management UI
 | 上海万序健康科技有限公司                    |
 | 上海中商网络股份有限公司                    |
 | 上海半天妖餐饮管理有限公司                  |
+| 上海杨国福企业管理(集团)有限公司          |
 | 上海契胜科技有限公司                        |
+| 纯米科技(上海)股份有限公司                |
+| 中腾信金融信息服务(上海)有限公司            |
 | GAP盖璞(上海)商业有限公司                 |
 | 汤臣倍健股份有限公司                        |
 | 跳羚科技(厦门)有限公司                      |
@@ -219,17 +227,14 @@ App Management UI
 | 山东埃德森石油工程技术有限公司              |
 | 山东第一医科大学第一附属医院                |
 | 广州无线电集团                              |
+| 广东小天才科技有限公司                      |
 | 广州携旅信息科技有限公司                    |
 | 广州蓝深科技有限公司                        |
 | 广州广汽商贸物流有限公司                    |
 | 广州思迈特软件有限公司                      |
+| 广州新一代人工智能产业园管理有限公司        |
 | 广东鸿正软件技术有限公司                    |
 | 广东汇天航空航天科技有限公司                |
-| 佛山众陶联供应链服务有限公司                |
-| 河南新辰环保科技有限公司                    |
-| 黄河科技集团有限公司                        |
-| 豫信电子科技集团有限公司                    |
-| 双汇物流投资有限公司                        |
 | 广东漫云物联科技有限公司                    |
 | 深圳市金溢科技股份有限公司                  |
 | 深圳市中悦科技有限公司                      |
@@ -238,23 +243,40 @@ App Management UI
 | 深圳云天励飞技术股份有限公司                |
 | 深圳市维玛科技有限公司                      |
 | 深圳市观塘银河电讯科技有限公司              |
+| 金龙机电股份有限公司                        |
+| 佛山众陶联供应链服务有限公司                |
+| 河南新辰环保科技有限公司                    |
+| 河南豫光金铅股份有限公司                    |
+| 黄河科技集团有限公司                        |
+| 豫信电子科技集团有限公司                    |
+| 双汇物流投资有限公司                        |
+| 北京外交人员服务局                          |
 | 北京博亚思科技有限公司                      |
 | 北京银泰置业有限公司                        |
 | 北京和融通支付科技有限公司                  |
 | 北京微通新成网络科技有限公司                |
 | 北京柏橡科技有限公司                        |
+| Best Lawyers Corporation(佳律)              |
 | 浙江领湾网络有限公司                        |
 | 浙江申跃信息科技有限公司                    |
 | 浙江一舟电子科技股份有限公司                |
+| 浙江正元智慧科技有限公司                    |
+| 浙江宇视科技有限公司                        |
+| 杭州市能源集团有限公司                      | 
 | 杭州润为数据科技有限公司                    |
 | 杭州马上自动化科技有限公司                  |
 | 景德镇黑猫集团有限责任公司                  |
+| 得力集实有限公司                            |
+| 海力控股集团有限公司                        |
 | 之江实验室                                  |
 | 丽水市中医医院                              |
 | 宁波金融资产交易中心                        |
 | 德清智慧教育平台                            |
 | 江苏创致信息科技有限公司                    |
 | 无锡市陶都巨龙软件有限责任公司              |
+| 苏州二叶制药有限公司                        |
+| 武汉良之隆食材股份有限公司                  |
+| 民生实业(集团)有限公司                    |
 | TCL华星光电技术有限公司                     |
 | 万宝盛华集团                                |
 | 妙盈科技                                    |
@@ -267,16 +289,19 @@ App Management UI
 | 广西数字浪潮数据服务有限公司                |
 | 百安居中国                                  |
 | 重庆两江协同创新区                          |
+| 重庆征信有限责任公司                        |
 | 万宝盛华大中华有限公司                      |
 | 哈尔滨途图科技有限公司                      |
 | 哈尔滨逐浪文化传媒有限公司                  |
 | 大连电瓷集团股份有限公司                    |
 | 锦州港股份有限公司                          |
+| 古汉中药有限公司                            |
 | 湖南数通信息技术服务有限公司                |
 | 湖南湘邮科技股份有限公司                    |
 | 湖南省公共资源交易平台市场主体注册系统      |
 | 湘潭智慧教育云统一认证平台                  |
 | 南京市智慧医疗投资运营服务有限公司          |
+| 南京领行科技股份有限公司                    |
 | 南凌科技股份有限公司                        |
 | 福建引迈信息技术有限公司                    |
 | 漳州信息产业集团有限公司                    |

+ 32 - 7
README_en.md

@@ -38,7 +38,7 @@ QQ: <b> 1054466084 </b>
 
 email: <b> support@maxsso.net </b>
 
-Code Hosting <a href="https://github.com/dromara/MaxKey" target="_blank"><b>GitHub</b></a> | <a href="https://gitee.com/dromara/MaxKey" target="_blank"><b>Gitee</b></a>
+Code Hosting <a href="https://github.com/dromara/MaxKey" target="_blank"><b>GitHub</b></a> | <a href="https://gitee.com/dromara/MaxKey" target="_blank"><b>Gitee</b></a>  | <a href="https://gitcode.com/dromara/MaxKey/overview" target="_blank"><b>GitCode</b></a>
 
 ><b> Single Sign On </b>(<b> SSO </b >),Users only need to login to the authentication center once , access all the trusted application systems without logging in again.
 >
@@ -120,7 +120,7 @@ App Management UI
 
 | Version    | Date   |   Download URL  |
 | --------   | :----- | :----           | 
-| v 4.0.5   | 2024/06/27   | <a href="https://www.maxkey.top/zh/about/download.html"  target="_blank">Download</a> |
+| v 4.1.1   | 2024/08/20   | <a href="https://www.maxkey.top/zh/about/download.html"  target="_blank">Download</a> |
 
 # Install
 
@@ -168,12 +168,15 @@ App Management UI
 | 单位    |
 | :-----  |
 | 中国人民警察大学                            |
+| 福耀科技大学                                |
 | 兰州现代职业学院                            |
 | 长春职业技术学院                            |
 | 云南师范大学                                |
 | 云南农业职业技术学院                        |
 | 惠州卫生职业技术学院                        |
+| 厦门软件职业技术学院                        |
 | 宜昌市三峡中等专业学校                      |
+| 上海图书馆                                  |
 | 重庆市北碚图书馆                            |
 | 天津市劳动保障技师学院                      |
 | 南京财经高等职业技术学校                    |
@@ -181,6 +184,7 @@ App Management UI
 | 余姚市教育局                                |
 | 中国金融认证中心                            |
 | 国家高端智能化家用电器创新中心              |
+| 国家中小企业数字化转型促进中心              |
 | 国元证券                                    |
 | 华夏金融租赁有限公司                        |
 | 国宝人寿保险股份有限公司                    |
@@ -194,6 +198,7 @@ App Management UI
 | 百度智能云身份管理服务                      |
 | 360公司                                     |
 | 三一华兴                                    |
+| 云小厨CloudKitchens                         |
 | 西藏阜康医院                                |
 | 海阳市人民医院                              |
 | 上海逸广信息科技有限公司                    |
@@ -201,7 +206,10 @@ App Management UI
 | 上海万序健康科技有限公司                    |
 | 上海中商网络股份有限公司                    |
 | 上海半天妖餐饮管理有限公司                  |
+| 上海杨国福企业管理(集团)有限公司          |
 | 上海契胜科技有限公司                        |
+| 纯米科技(上海)股份有限公司                |
+| 中腾信金融信息服务(上海)有限公司            |
 | GAP盖璞(上海)商业有限公司                 |
 | 汤臣倍健股份有限公司                        |
 | 跳羚科技(厦门)有限公司                      |
@@ -218,17 +226,14 @@ App Management UI
 | 山东埃德森石油工程技术有限公司              |
 | 山东第一医科大学第一附属医院                |
 | 广州无线电集团                              |
+| 广东小天才科技有限公司                      |
 | 广州携旅信息科技有限公司                    |
 | 广州蓝深科技有限公司                        |
 | 广州广汽商贸物流有限公司                    |
 | 广州思迈特软件有限公司                      |
+| 广州新一代人工智能产业园管理有限公司        |
 | 广东鸿正软件技术有限公司                    |
 | 广东汇天航空航天科技有限公司                |
-| 佛山众陶联供应链服务有限公司                |
-| 河南新辰环保科技有限公司                    |
-| 黄河科技集团有限公司                        |
-| 豫信电子科技集团有限公司                    |
-| 双汇物流投资有限公司                        |
 | 广东漫云物联科技有限公司                    |
 | 深圳市金溢科技股份有限公司                  |
 | 深圳市中悦科技有限公司                      |
@@ -237,23 +242,40 @@ App Management UI
 | 深圳云天励飞技术股份有限公司                |
 | 深圳市维玛科技有限公司                      |
 | 深圳市观塘银河电讯科技有限公司              |
+| 金龙机电股份有限公司                        |
+| 佛山众陶联供应链服务有限公司                |
+| 河南新辰环保科技有限公司                    |
+| 河南豫光金铅股份有限公司                    |
+| 黄河科技集团有限公司                        |
+| 豫信电子科技集团有限公司                    |
+| 双汇物流投资有限公司                        |
+| 北京外交人员服务局                          |
 | 北京博亚思科技有限公司                      |
 | 北京银泰置业有限公司                        |
 | 北京和融通支付科技有限公司                  |
 | 北京微通新成网络科技有限公司                |
 | 北京柏橡科技有限公司                        |
+| Best Lawyers Corporation(佳律)              |
 | 浙江领湾网络有限公司                        |
 | 浙江申跃信息科技有限公司                    |
 | 浙江一舟电子科技股份有限公司                |
+| 浙江正元智慧科技有限公司                    |
+| 浙江宇视科技有限公司                        |
+| 杭州市能源集团有限公司                      | 
 | 杭州润为数据科技有限公司                    |
 | 杭州马上自动化科技有限公司                  |
 | 景德镇黑猫集团有限责任公司                  |
+| 得力集实有限公司                            |
+| 海力控股集团有限公司                        |
 | 之江实验室                                  |
 | 丽水市中医医院                              |
 | 宁波金融资产交易中心                        |
 | 德清智慧教育平台                            |
 | 江苏创致信息科技有限公司                    |
 | 无锡市陶都巨龙软件有限责任公司              |
+| 苏州二叶制药有限公司                        |
+| 武汉良之隆食材股份有限公司                  |
+| 民生实业(集团)有限公司                    |
 | TCL华星光电技术有限公司                     |
 | 万宝盛华集团                                |
 | 妙盈科技                                    |
@@ -266,16 +288,19 @@ App Management UI
 | 广西数字浪潮数据服务有限公司                |
 | 百安居中国                                  |
 | 重庆两江协同创新区                          |
+| 重庆征信有限责任公司                        |
 | 万宝盛华大中华有限公司                      |
 | 哈尔滨途图科技有限公司                      |
 | 哈尔滨逐浪文化传媒有限公司                  |
 | 大连电瓷集团股份有限公司                    |
 | 锦州港股份有限公司                          |
+| 古汉中药有限公司                            |
 | 湖南数通信息技术服务有限公司                |
 | 湖南湘邮科技股份有限公司                    |
 | 湖南省公共资源交易平台市场主体注册系统      |
 | 湘潭智慧教育云统一认证平台                  |
 | 南京市智慧医疗投资运营服务有限公司          |
+| 南京领行科技股份有限公司                    |
 | 南凌科技股份有限公司                        |
 | 福建引迈信息技术有限公司                    |
 | 漳州信息产业集团有限公司                    |

+ 32 - 7
README_zh.md

@@ -38,7 +38,7 @@ MaxKey注重企业级场景下的性能、安全和易用性,广泛应用于
 
 邮箱email: <b>support@maxsso.net</b>
 
-代码托管 <a href="https://gitee.com/dromara/MaxKey" target="_blank"><b>Gitee</b></a> | <a href="https://github.com/dromara/MaxKey" target="_blank"><b>GitHub</b></a>
+代码托管 <a href="https://gitee.com/dromara/MaxKey" target="_blank"><b>Gitee</b></a> | <a href="https://github.com/dromara/MaxKey" target="_blank"><b>GitHub</b></a> | <a href="https://gitcode.com/dromara/MaxKey/overview" target="_blank"><b>GitCode</b></a>
 
  
 ><b>单点登录(Single Sign On)</b>简称为<b>SSO</b>,用户只需要登录认证中心一次就可以访问所有相互信任的应用系统,无需再次登录。
@@ -121,7 +121,7 @@ MaxKey注重企业级场景下的性能、安全和易用性,广泛应用于
 
 | 版本       | 日期    |  下载              | 
 | --------   | :-----  | :----              | 
-| v 4.0.5   | 2024/06/27   | <a href="https://www.maxkey.top/zh/about/download.html" target="_blank">下载</a>|
+| v 4.1.1   | 2024/08/20   | <a href="https://www.maxkey.top/zh/about/download.html" target="_blank">下载</a>|
  
  
 # 安装部署
@@ -172,12 +172,15 @@ MaxKey注重企业级场景下的性能、安全和易用性,广泛应用于
 | 单位    |
 | :-----  |
 | 中国人民警察大学                            |
+| 福耀科技大学                                |
 | 兰州现代职业学院                            |
 | 长春职业技术学院                            |
 | 云南师范大学                                |
 | 云南农业职业技术学院                        |
 | 惠州卫生职业技术学院                        |
+| 厦门软件职业技术学院                        |
 | 宜昌市三峡中等专业学校                      |
+| 上海图书馆                                  |
 | 重庆市北碚图书馆                            |
 | 天津市劳动保障技师学院                      |
 | 南京财经高等职业技术学校                    |
@@ -185,6 +188,7 @@ MaxKey注重企业级场景下的性能、安全和易用性,广泛应用于
 | 余姚市教育局                                |
 | 中国金融认证中心                            |
 | 国家高端智能化家用电器创新中心              |
+| 国家中小企业数字化转型促进中心              |
 | 国元证券                                    |
 | 华夏金融租赁有限公司                        |
 | 国宝人寿保险股份有限公司                    |
@@ -198,6 +202,7 @@ MaxKey注重企业级场景下的性能、安全和易用性,广泛应用于
 | 百度智能云身份管理服务                      |
 | 360公司                                     |
 | 三一华兴                                    |
+| 云小厨CloudKitchens                         |
 | 西藏阜康医院                                |
 | 海阳市人民医院                              |
 | 上海逸广信息科技有限公司                    |
@@ -205,7 +210,10 @@ MaxKey注重企业级场景下的性能、安全和易用性,广泛应用于
 | 上海万序健康科技有限公司                    |
 | 上海中商网络股份有限公司                    |
 | 上海半天妖餐饮管理有限公司                  |
+| 上海杨国福企业管理(集团)有限公司          |
 | 上海契胜科技有限公司                        |
+| 纯米科技(上海)股份有限公司                |
+| 中腾信金融信息服务(上海)有限公司            |
 | GAP盖璞(上海)商业有限公司                 |
 | 汤臣倍健股份有限公司                        |
 | 跳羚科技(厦门)有限公司                      |
@@ -222,17 +230,14 @@ MaxKey注重企业级场景下的性能、安全和易用性,广泛应用于
 | 山东埃德森石油工程技术有限公司              |
 | 山东第一医科大学第一附属医院                |
 | 广州无线电集团                              |
+| 广东小天才科技有限公司                      |
 | 广州携旅信息科技有限公司                    |
 | 广州蓝深科技有限公司                        |
 | 广州广汽商贸物流有限公司                    |
 | 广州思迈特软件有限公司                      |
+| 广州新一代人工智能产业园管理有限公司        |
 | 广东鸿正软件技术有限公司                    |
 | 广东汇天航空航天科技有限公司                |
-| 佛山众陶联供应链服务有限公司                |
-| 河南新辰环保科技有限公司                    |
-| 黄河科技集团有限公司                        |
-| 豫信电子科技集团有限公司                    |
-| 双汇物流投资有限公司                        |
 | 广东漫云物联科技有限公司                    |
 | 深圳市金溢科技股份有限公司                  |
 | 深圳市中悦科技有限公司                      |
@@ -241,23 +246,40 @@ MaxKey注重企业级场景下的性能、安全和易用性,广泛应用于
 | 深圳云天励飞技术股份有限公司                |
 | 深圳市维玛科技有限公司                      |
 | 深圳市观塘银河电讯科技有限公司              |
+| 金龙机电股份有限公司                        |
+| 佛山众陶联供应链服务有限公司                |
+| 河南新辰环保科技有限公司                    |
+| 河南豫光金铅股份有限公司                    |
+| 黄河科技集团有限公司                        |
+| 豫信电子科技集团有限公司                    |
+| 双汇物流投资有限公司                        |
+| 北京外交人员服务局                          |
 | 北京博亚思科技有限公司                      |
 | 北京银泰置业有限公司                        |
 | 北京和融通支付科技有限公司                  |
 | 北京微通新成网络科技有限公司                |
 | 北京柏橡科技有限公司                        |
+| Best Lawyers Corporation(佳律)              |
 | 浙江领湾网络有限公司                        |
 | 浙江申跃信息科技有限公司                    |
 | 浙江一舟电子科技股份有限公司                |
+| 浙江正元智慧科技有限公司                    |
+| 浙江宇视科技有限公司                        |
+| 杭州市能源集团有限公司                      | 
 | 杭州润为数据科技有限公司                    |
 | 杭州马上自动化科技有限公司                  |
 | 景德镇黑猫集团有限责任公司                  |
+| 得力集实有限公司                            |
+| 海力控股集团有限公司                        |
 | 之江实验室                                  |
 | 丽水市中医医院                              |
 | 宁波金融资产交易中心                        |
 | 德清智慧教育平台                            |
 | 江苏创致信息科技有限公司                    |
 | 无锡市陶都巨龙软件有限责任公司              |
+| 苏州二叶制药有限公司                        |
+| 武汉良之隆食材股份有限公司                  |
+| 民生实业(集团)有限公司                    |
 | TCL华星光电技术有限公司                     |
 | 万宝盛华集团                                |
 | 妙盈科技                                    |
@@ -270,16 +292,19 @@ MaxKey注重企业级场景下的性能、安全和易用性,广泛应用于
 | 广西数字浪潮数据服务有限公司                |
 | 百安居中国                                  |
 | 重庆两江协同创新区                          |
+| 重庆征信有限责任公司                        |
 | 万宝盛华大中华有限公司                      |
 | 哈尔滨途图科技有限公司                      |
 | 哈尔滨逐浪文化传媒有限公司                  |
 | 大连电瓷集团股份有限公司                    |
 | 锦州港股份有限公司                          |
+| 古汉中药有限公司                            |
 | 湖南数通信息技术服务有限公司                |
 | 湖南湘邮科技股份有限公司                    |
 | 湖南省公共资源交易平台市场主体注册系统      |
 | 湘潭智慧教育云统一认证平台                  |
 | 南京市智慧医疗投资运营服务有限公司          |
+| 南京领行科技股份有限公司                    |
 | 南凌科技股份有限公司                        |
 | 福建引迈信息技术有限公司                    |
 | 漳州信息产业集团有限公司                    |

+ 28 - 1
ReleaseNotes.txt

@@ -1,4 +1,31 @@
-MaxKey v 4.0.5 GA 2024/06/27
+MaxKey v 4.1.1 GA 2024/08/20
+    *(MAXKEY-240501) 构建方式优化
+    *(MAXKEY-240502) 修复jwks转义问题 @奇健陀螺王
+    *(MAXKEY-240503) 增加删除确认提醒
+    *(MAXKEY-240504) 批量删除按钮文字调整
+    *(MAXKEY-240505) 应用访问权限修复
+    *(MAXKEY-240506) 个人资料、密码修改优化
+    *(MAXKEY-240507) APP扫码登录支持
+    *(MAXKEY-240508) 历史日志数量从100改为15
+    *(MAXKEY-240509) @Bean public to default
+	*(MAXKEY-240510) 大量框架代码的优化
+    *(MAXKEY-240511) 依赖项引用、更新和升级
+		
+MaxKey v 4.1.0 GA 2024/07/19
+    *(MAXKEY-240401) 本地StringUtils 调整成 StrUtils ,取消org.apache.commons.lang3.StringUtils继承关系
+    *(MAXKEY-240402) 功能模块化,调整通用模块为starter,包括模块captcha、ip2location、otp、sms、web
+    *(MAXKEY-240403) 定时任务优化
+    *(MAXKEY-240404) 调整用户组成员管理的用户组为列表
+    *(MAXKEY-240405) 调整访问控制的用户组为列表
+    *(MAXKEY-240406) 增加权限管理的应用列表界面,通过应用列表中的按钮管理应用资源和权限授予
+    *(MAXKEY-240407) 单点登录日志记录时间为空问题修复
+    *(MAXKEY-240408) gradle-wrapper.properties地址优化 @杨坡 <yanghbu@163.com>
+    *(MAXKEY-240409) 数据访问层升级和优化
+	*(MAXKEY-240410) AutoConfiguration自动加载优化
+    *(MAXKEY-240411) 依赖项引用、更新和升级
+        mybatis-jpa-extra               3.3.0
+
+MaxKey v 4.0.5 GA 2024/06/27
     *(MAXKEY-240301) ProductVersionEndpoint 显示产品版本信息
     *(MAXKEY-240302) WARN No Root logger was configured, creating default ERROR-level Root logger with Console appender 优化配置
     *(MAXKEY-240303) ConfigurerFreeMarker代码优化

+ 12 - 12
build_cnf.gradle

@@ -33,30 +33,30 @@ task clearBuild(){
 	delete "$rootDir/maxkey-webs/maxkey-web-openapi/build.gradle"	
 }
 
-task configStd(dependsOn:['clearBuild']) {
+task configTradition(dependsOn:['clearBuild']) {
 	doLast {
 		copy {
-			from "$rootDir/maxkey-webs/maxkey-web-openapi/config/build_standard.gradle"
+			from "$rootDir/maxkey-webs/maxkey-web-openapi/config/build_tradition.gradle"
 			into "$rootDir/maxkey-webs/maxkey-web-openapi/"
 			rename { String fileName -> 'build.gradle' }
 		}
 		copy {
-			from "$rootDir/maxkey-webs/maxkey-web-mgt/config/build_standard.gradle"
+			from "$rootDir/maxkey-webs/maxkey-web-mgt/config/build_tradition.gradle"
 			into "$rootDir/maxkey-webs/maxkey-web-mgt/"
 			rename { String fileName -> 'build.gradle' }
 		}
 		copy {
-			from "$rootDir/maxkey-webs/maxkey-web-maxkey/config/build_standard.gradle"
+			from "$rootDir/maxkey-webs/maxkey-web-maxkey/config/build_tradition.gradle"
 			into "$rootDir/maxkey-webs/maxkey-web-maxkey/"
 			rename { String fileName -> 'build.gradle' }
 		}
 		copy {
-			from "$rootDir/config/build_standard.gradle"
+			from "$rootDir/config/build_tradition.gradle"
 			into "$rootDir/"
 			rename { String fileName -> 'build.gradle' }
 		}
 		
-		println 'Standard Build MaxKey .'
+		println 'Tradition Build MaxKey .'
 	}
 }
 
@@ -91,32 +91,32 @@ task configDocker(dependsOn:['clearBuild']) {
 
 
 
-task configJar(dependsOn:['clearBuild']) {
+task configStandard(dependsOn:['clearBuild']) {
 	doLast {
 		copy {
-			from "$rootDir/maxkey-webs/maxkey-web-openapi/config/build_jar.gradle"
+			from "$rootDir/maxkey-webs/maxkey-web-openapi/config/build_standard.gradle"
 			into "$rootDir/maxkey-webs/maxkey-web-openapi/"
 			rename { String fileName -> 'build.gradle' }
 		}
 		copy {
-			from "$rootDir/maxkey-webs/maxkey-web-mgt/config/build_jar.gradle"
+			from "$rootDir/maxkey-webs/maxkey-web-mgt/config/build_standard.gradle"
 			into "$rootDir/maxkey-webs/maxkey-web-mgt/"
 			rename { String fileName -> 'build.gradle' }
 		}
 		
 		copy {
-			from "$rootDir/maxkey-webs/maxkey-web-maxkey/config/build_jar.gradle"
+			from "$rootDir/maxkey-webs/maxkey-web-maxkey/config/build_standard.gradle"
 			into "$rootDir/maxkey-webs/maxkey-web-maxkey/"
 			rename { String fileName -> 'build.gradle' }
 		}
 		
 		copy {
-			from "$rootDir/config/build_jar.gradle"
+			from "$rootDir/config/build_standard.gradle"
 			into "$rootDir/"
 			rename { String fileName -> 'build.gradle' }
 		}
 
-		println 'Java Jar Build MaxKey .'
+		println 'Standard Build MaxKey .'
 	}
 }
 

+ 63 - 144
config/build_standard.gradle

@@ -22,47 +22,11 @@ defaultTasks "clean", "build"
 
 //Version define
 ext {
-    
+	
 }
 
-def libjarsmapper=[
-    'maxkey-authentication-captcha'         :'lib',
-    'maxkey-authentication-core'            :'lib',
-    'maxkey-authentication-ip2region'       :'lib',
-    'maxkey-authentication-otp'             :'lib',
-    'maxkey-authentication-provider'        :'lib',
-    'maxkey-authentication-sms'             :'lib',
-    'maxkey-common'                         :'lib',
-    'maxkey-core'                           :'lib',
-    'maxkey-persistence'                    :'lib',
-    'maxkey-protocol-authorize'             :'lib',
-    'maxkey-protocol-cas'                   :'lib',
-    'maxkey-protocol-desktop'               :'lib',
-    'maxkey-protocol-extendapi'             :'lib',
-    'maxkey-protocol-formbased'             :'lib',
-    'maxkey-protocol-jwt'                   :'lib',
-    'maxkey-protocol-oauth-2.0'             :'lib',
-    'maxkey-protocol-saml-2.0'              :'lib',
-    'maxkey-protocol-tokenbased'            :'lib',
-    'maxkey-web-resources'                  :'lib',
-    'maxkey-authentication-social'          :'maxkey',
-    'maxkey-web-maxkey'                     :'maxkey',
-    'maxkey-web-mgt'                        :'maxkey_mgt',
-    'maxkey-synchronizer'                   :'maxkey_mgt',
-    'maxkey-synchronizer-activedirectory'   :'maxkey_mgt',
-    'maxkey-synchronizer-common'            :'maxkey_mgt',
-    'maxkey-synchronizer-jdbc'              :'maxkey_mgt',
-    'maxkey-synchronizer-ldap'              :'maxkey_mgt',
-    'maxkey-synchronizer-dingtalk'          :'maxkey_mgt',
-    'maxkey-synchronizer-workweixin'        :'maxkey_mgt',
-    'maxkey-synchronizer-reorgdept'         :'maxkey_mgt',
-    'maxkey-web-openapi'                    :'maxkey_openapi',
-    'maxkey-web-api-rest'                   :'maxkey_openapi',
-    'maxkey-web-api-scim'                   :'maxkey_openapi',
-]
-
 configurations.all {
-    transitive = false// 为本依赖关闭依赖传递特性
+	transitive = false// 为本依赖关闭依赖传递特性
 }
 
 //add support for Java
@@ -74,14 +38,14 @@ allprojects {
     //apply plugin: "findbugs"
     //apply plugin: "jdepend"
     
-    configurations.all {
-        transitive = false// 为本依赖关闭依赖传递特性
-    }   
-    //java Version
-    sourceCompatibility = 17
-    targetCompatibility = 17
-    compileJava.options.encoding = 'UTF-8'
-    
+	configurations.all {
+		transitive = false// 为本依赖关闭依赖传递特性
+	}	
+	//java Version
+	sourceCompatibility = 17
+	targetCompatibility	= 17
+	compileJava.options.encoding = 'UTF-8'
+	
     eclipse {
         /*设置工程字符集*/
         jdt  {
@@ -91,7 +55,7 @@ allprojects {
                 prefs.append('encoding/<project>=UTF-8') //use UTF-8
             }
         }
-    }  
+    } 
 }
 
 buildscript {
@@ -105,28 +69,37 @@ repositories {
     // Use 'jcenter' for resolving your dependencies.
     // You can declare any Maven/Ivy/file repository here.
     mavenCentral()
+    jcenter()
     
 }
 
-// In this section you declare the dependencies for your production and test code
-dependencies {
- 
-}
 
-subprojects {
-    processResources {
-        from ('src/main/resources') {
-            include 'src/main/resources/*.*'
-        }
-    }
-    sourceSets {
-        main {
-            java {
-                srcDir 'src/main/java' // 指定源码目录
-            }
-         }
-    }
-    repositories {  
+
+subprojects {  	
+	/*
+	eclipse {
+		第一次时请注释这段eclipse设置,可能报错,设置工程字符集
+		jdt  {
+		    File f = file('.settings/org.eclipse.core.resources.prefs')
+		    f.write('eclipse.preferences.version=1\n')
+		    f.append('encoding/<project>=UTF-8') //use UTF-8
+		}
+	}
+	*/
+	processResources {
+		from ('src/main/resources') {
+	    	include 'src/main/resources/*.*'
+	  	}
+	}
+	sourceSets {
+	    main {
+	        java {
+	            srcDir 'src/main/java' // 指定源码目录
+	        }
+	   	 }
+	}
+	
+	repositories {  
         mavenLocal()
         maven { url "https://maven.aliyun.com/repository/central"}
         maven { url "https://maven.aliyun.com/repository/public"}
@@ -143,8 +116,8 @@ subprojects {
         maven { url "https://repository.apache.org/content/repositories/releases" }
         mavenCentral()
     }  
-
-    //all dependencies
+	
+	//all dependencies
     dependencies {
          //for Test and Compile
          testImplementation group: 'junit', name: 'junit', version: "${junitVersion}"
@@ -447,92 +420,38 @@ subprojects {
     
     jar {  
 
-        def currentTime = java.time.ZonedDateTime.now()
-        manifest {
-            attributes(
-                        "Implementation-Title": project.name,
-                        "Implementation-Vendor": project.vendor,
-                        "Created-By": project.author,
-                        "Implementation-Date": currentTime,
-                        "Implementation-Version": project.version
-               )
-        }
-    }
-    
-    tasks.register("buildRelease",Copy) {
-        dependsOn   assemble
-        //项目名 项目所在的group version 版本号
-        println  "subproject " + project.name + ", group " + project.group +" , version " + project.version
-        
-        //copy
-        into "$rootDir/build/maxkey-jars/"
-        from "$buildDir/libs/"
-        include '*.jar'
-    }
-    
-    tasks.register("copyLibJars",Copy) {
-        if (libjarsmapper["${project.name}"] != null){
-              into "$rootDir/build/MaxKey-v${project.version}GA/"+libjarsmapper["${project.name}"]
-              from "$buildDir/libs/"
-              include '*.jar'
-        }
-    }
-    assemble.configure { finalizedBy buildRelease,copyLibJars }
-}
+	    def currentTime = java.time.ZonedDateTime.now()
+	    manifest {
+	        attributes(
+						"Implementation-Title": project.name,
+	                	"Implementation-Vendor": project.vendor,
+	                	"Created-By": project.author,
+	                	"Implementation-Date": currentTime,
+	                	"Implementation-Version": project.version
+	           )
+	    }
+	}
+	
+	task buildRelease()  {
+		dependsOn	assemble
+		//项目名
+		println  "subproject " + project.name + ", group " + project.group +" , version " + project.version
+	}
+	
+	assemble.configure { finalizedBy buildRelease }
 
-//copy Dep Jars to /build/maxkey-depjars,only maxkey-common deps
-project('maxkey-common')  {
-    task createReleaseDir(type: Copy){
-        def paths = ["$rootDir/build/MaxKey-v${project.version}GA",
-                     "$rootDir/build/MaxKey-v${project.version}GA/maxkey",
-                     "$rootDir/build/MaxKey-v${project.version}GA/maxkey_mgt",
-                     "$rootDir/build/MaxKey-v${project.version}GA/lib"];
-        //遍历数组,调用createDir闭包,创建目录
-        paths.forEach(){path->
-            File dir=new File(path);
-            if (!dir.exists()){
-                print("create "+path+"\n")
-                dir.mkdirs();
-            }
-        };
-    }
-    
-    task copyDepJars (type: Copy){
-        dependsOn   assemble
-        println  "copy Dep Jars to $rootDir/build/MaxKey-v${project.version}GA/lib"
-        //copy runtime
-        from configurations.runtimeClasspath
-        into "$rootDir/build/MaxKey-v${project.version}GA/lib";
-    }
-    
-    build.configure { finalizedBy copyDepJars }
 }
 
 tasks.register("buildRelease")  {
-    dependsOn 'copyShellScript','copyWindowsShellScript'
-    
     //项目名 项目所在的group version 版本号
     println  "Root project " + project.name + ", group " + project.group +" , version " + project.version
     //项目的绝对路径 to 项目的build文件绝对路径
     println "Root project projectDir " + project.projectDir +" to " + project.buildDir
 }
 
-tasks.register("copyShellScript",Copy) {
-    println  "project copyMaxKeyShellScript .";
-    
-    from "$rootDir/shellscript/"
-    into "$rootDir/build/MaxKey-v${project.version}GA/shellscript/";
-}
-
-tasks.register("copyWindowsShellScript",Copy) {
-    println  "project copyMaxKeyWindowsShellScript .";
-    from "$rootDir/shellscript/windows"
-    into "$rootDir/build/MaxKey-v${project.version}GA/";
-}
+build.configure { finalizedBy buildRelease }
 
-build.configure { 
-	finalizedBy buildRelease 
-	
-	println ""
-	println "Gradle version is ${GradleVersion.current().version}"
+// In this section you declare the dependencies for your production and test code
+dependencies {
+ 
 }

+ 148 - 64
config/build_jar.gradle → config/build_tradition.gradle

@@ -1,5 +1,5 @@
 /*
- * Copyright [2023] [MaxKey of copyright http://www.maxkey.top]
+ * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,11 +22,50 @@ defaultTasks "clean", "build"
 
 //Version define
 ext {
-	
+    
 }
 
+def libjarsmapper=[
+    'maxkey-authentication-core'            :'lib',
+    'maxkey-authentication-provider'        :'lib',
+    'maxkey-common'                         :'lib',
+    'maxkey-core'                           :'lib',
+    'maxkey-persistence'                    :'lib',
+    'maxkey-protocol-authorize'             :'lib',
+    'maxkey-protocol-cas'                   :'lib',
+    'maxkey-protocol-desktop'               :'lib',
+    'maxkey-protocol-extendapi'             :'lib',
+    'maxkey-protocol-formbased'             :'lib',
+    'maxkey-protocol-jwt'                   :'lib',
+    'maxkey-protocol-oauth-2.0'             :'lib',
+    'maxkey-protocol-saml-2.0'              :'lib',
+    'maxkey-protocol-tokenbased'            :'lib',
+	'maxkey-starter-captcha'            	:'lib',
+	'maxkey-starter-ip2location'            :'lib',
+	'maxkey-starter-otp'            		:'lib',
+	'maxkey-starter-sms'            		:'lib',
+	'maxkey-starter-web'            		:'lib',
+	
+    'maxkey-authentication-social'          :'maxkey',
+    'maxkey-web-maxkey'                     :'maxkey',
+	
+    'maxkey-web-mgt'                        :'maxkey_mgt',
+    'maxkey-synchronizer'                   :'maxkey_mgt',
+    'maxkey-synchronizer-activedirectory'   :'maxkey_mgt',
+    'maxkey-synchronizer-common'            :'maxkey_mgt',
+    'maxkey-synchronizer-jdbc'              :'maxkey_mgt',
+    'maxkey-synchronizer-ldap'              :'maxkey_mgt',
+    'maxkey-synchronizer-dingtalk'          :'maxkey_mgt',
+    'maxkey-synchronizer-workweixin'        :'maxkey_mgt',
+    'maxkey-synchronizer-reorgdept'         :'maxkey_mgt',
+	
+    'maxkey-web-openapi'                    :'maxkey_openapi',
+    'maxkey-web-api-rest'                   :'maxkey_openapi',
+    'maxkey-web-api-scim'                   :'maxkey_openapi',
+]
+	
 configurations.all {
-	transitive = false// 为本依赖关闭依赖传递特性
+    transitive = false// 为本依赖关闭依赖传递特性
 }
 
 //add support for Java
@@ -38,14 +77,14 @@ allprojects {
     //apply plugin: "findbugs"
     //apply plugin: "jdepend"
     
-	configurations.all {
-		transitive = false// 为本依赖关闭依赖传递特性
-	}	
-	//java Version
-	sourceCompatibility = 17
-	targetCompatibility	= 17
-	compileJava.options.encoding = 'UTF-8'
-	
+    configurations.all {
+        transitive = false// 为本依赖关闭依赖传递特性
+    }   
+    //java Version
+    sourceCompatibility = 17
+    targetCompatibility = 17
+    compileJava.options.encoding = 'UTF-8'
+    
     eclipse {
         /*设置工程字符集*/
         jdt  {
@@ -55,7 +94,7 @@ allprojects {
                 prefs.append('encoding/<project>=UTF-8') //use UTF-8
             }
         }
-    } 
+    }  
 }
 
 buildscript {
@@ -69,37 +108,28 @@ repositories {
     // Use 'jcenter' for resolving your dependencies.
     // You can declare any Maven/Ivy/file repository here.
     mavenCentral()
-    jcenter()
     
 }
 
+// In this section you declare the dependencies for your production and test code
+dependencies {
+ 
+}
 
-
-subprojects {  	
-	/*
-	eclipse {
-		第一次时请注释这段eclipse设置,可能报错,设置工程字符集
-		jdt  {
-		    File f = file('.settings/org.eclipse.core.resources.prefs')
-		    f.write('eclipse.preferences.version=1\n')
-		    f.append('encoding/<project>=UTF-8') //use UTF-8
-		}
-	}
-	*/
-	processResources {
-		from ('src/main/resources') {
-	    	include 'src/main/resources/*.*'
-	  	}
-	}
-	sourceSets {
-	    main {
-	        java {
-	            srcDir 'src/main/java' // 指定源码目录
-	        }
-	   	 }
-	}
-	
-	repositories {  
+subprojects {
+    processResources {
+        from ('src/main/resources') {
+            include 'src/main/resources/*.*'
+        }
+    }
+    sourceSets {
+        main {
+            java {
+                srcDir 'src/main/java' // 指定源码目录
+            }
+         }
+    }
+    repositories {  
         mavenLocal()
         maven { url "https://maven.aliyun.com/repository/central"}
         maven { url "https://maven.aliyun.com/repository/public"}
@@ -116,8 +146,8 @@ subprojects {
         maven { url "https://repository.apache.org/content/repositories/releases" }
         mavenCentral()
     }  
-	
-	//all dependencies
+
+    //all dependencies
     dependencies {
          //for Test and Compile
          testImplementation group: 'junit', name: 'junit', version: "${junitVersion}"
@@ -420,38 +450,92 @@ subprojects {
     
     jar {  
 
-	    def currentTime = java.time.ZonedDateTime.now()
-	    manifest {
-	        attributes(
-						"Implementation-Title": project.name,
-	                	"Implementation-Vendor": project.vendor,
-	                	"Created-By": project.author,
-	                	"Implementation-Date": currentTime,
-	                	"Implementation-Version": project.version
-	           )
-	    }
-	}
-	
-	task buildRelease()  {
-		dependsOn	assemble
-		//项目名
-		println  "subproject " + project.name + ", group " + project.group +" , version " + project.version
-	}
-	
-	assemble.configure { finalizedBy buildRelease }
+        def currentTime = java.time.ZonedDateTime.now()
+        manifest {
+            attributes(
+                        "Implementation-Title": project.name,
+                        "Implementation-Vendor": project.vendor,
+                        "Created-By": project.author,
+                        "Implementation-Date": currentTime,
+                        "Implementation-Version": project.version
+               )
+        }
+    }
+    
+    tasks.register("buildRelease",Copy) {
+        dependsOn   assemble
+        //项目名 项目所在的group version 版本号
+        println  "subproject " + project.name + ", group " + project.group +" , version " + project.version
+        
+        //copy
+        into "$rootDir/build/maxkey-jars/"
+        from "$buildDir/libs/"
+        include '*.jar'
+    }
+    
+    tasks.register("copyLibJars",Copy) {
+        if (libjarsmapper["${project.name}"] != null){
+              into "$rootDir/build/MaxKey-v${project.version}GA/"+libjarsmapper["${project.name}"]
+              from "$buildDir/libs/"
+              include '*.jar'
+        }
+    }
+    assemble.configure { finalizedBy buildRelease,copyLibJars }
+}
 
+//copy Dep Jars to /build/maxkey-depjars,only maxkey-common deps
+project('maxkey-common')  {
+    task createReleaseDir(type: Copy){
+        def paths = ["$rootDir/build/MaxKey-v${project.version}GA",
+                     "$rootDir/build/MaxKey-v${project.version}GA/maxkey",
+                     "$rootDir/build/MaxKey-v${project.version}GA/maxkey_mgt",
+                     "$rootDir/build/MaxKey-v${project.version}GA/lib"];
+        //遍历数组,调用createDir闭包,创建目录
+        paths.forEach(){path->
+            File dir=new File(path);
+            if (!dir.exists()){
+                print("create "+path+"\n")
+                dir.mkdirs();
+            }
+        };
+    }
+    
+    task copyDepJars (type: Copy){
+        dependsOn   assemble
+        println  "copy Dep Jars to $rootDir/build/MaxKey-v${project.version}GA/lib"
+        //copy runtime
+        from configurations.runtimeClasspath
+        into "$rootDir/build/MaxKey-v${project.version}GA/lib";
+    }
+    
+    build.configure { finalizedBy copyDepJars }
 }
 
 tasks.register("buildRelease")  {
+    dependsOn 'copyShellScript','copyWindowsShellScript'
+    
     //项目名 项目所在的group version 版本号
     println  "Root project " + project.name + ", group " + project.group +" , version " + project.version
     //项目的绝对路径 to 项目的build文件绝对路径
     println "Root project projectDir " + project.projectDir +" to " + project.buildDir
 }
 
-build.configure { finalizedBy buildRelease }
+tasks.register("copyShellScript",Copy) {
+    println  "project copyMaxKeyShellScript .";
+    
+    from "$rootDir/shellscript/"
+    into "$rootDir/build/MaxKey-v${project.version}GA/shellscript/";
+}
 
-// In this section you declare the dependencies for your production and test code
-dependencies {
- 
+tasks.register("copyWindowsShellScript",Copy) {
+    println  "project copyMaxKeyWindowsShellScript .";
+    from "$rootDir/shellscript/windows"
+    into "$rootDir/build/MaxKey-v${project.version}GA/";
+}
+
+build.configure { 
+	finalizedBy buildRelease 
+	
+	println ""
+	println "Gradle version is ${GradleVersion.current().version}"
 }

+ 6 - 6
gradle.properties

@@ -15,7 +15,7 @@
 # */
 #maxkey properties 
 group                           =org.dromara.maxkey
-version                         =4.0.5
+version                         =4.1.1
 vendor                          =https://www.maxkey.top
 author                          =MaxKeyTop
 githubUrl						=https://github.com/dromara/MaxKey
@@ -32,10 +32,10 @@ jibToAuthPassword               =docker registry credential
 
 #maxkey used jars version
 #spring 
-springVersion                   =6.1.8
-springBootVersion               =3.3.0
-springSecurityVersion           =6.3.0
-springDataVersion               =3.3.0
+springVersion                   =6.1.13
+springBootVersion               =3.3.4
+springSecurityVersion           =6.3.3
+springDataVersion               =3.3.4
 springkafkaVersion              =3.2.0
 springretryVersion              =1.3.3
 #spring plugin
@@ -82,7 +82,7 @@ freemarkerVersion               =2.3.32
 xmlbeansVersion                 =5.0.2
 poiVersion                      =5.2.3
 #tomcat
-tomcatVersion                   =10.1.23
+tomcatVersion                   =10.1.30
 #logs
 log4jVersion                    =2.23.1
 slf4jVersion                    =2.0.13

+ 1 - 1
gradle/wrapper/gradle-wrapper.properties

@@ -1,6 +1,6 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
+distributionUrl=https://services.gradle.org/distributions/gradle-8.8-bin.zip
 networkTimeout=10000
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists

+ 1 - 1
maxkey-authentications/maxkey-authentication-core/build.gradle

@@ -9,6 +9,6 @@ dependencies {
 	implementation project(":maxkey-common")
 	implementation project(":maxkey-core")
 	implementation project(":maxkey-persistence")
-   	implementation project(":maxkey-authentications:maxkey-authentication-otp")
+   	implementation project(":maxkey-starter:maxkey-starter-otp")
    
 }

+ 59 - 0
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/QrCodeCredentialDto.java

@@ -0,0 +1,59 @@
+/*
+ * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.dromara.maxkey.authn;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotEmpty;
+
+import java.io.Serial;
+import java.io.Serializable;
+
+/**
+ * @description:
+ * @author: orangeBabu
+ * @time: 16/8/2024 AM10:54
+ */
+
+
+public class QrCodeCredentialDto {
+
+
+    @NotEmpty(message = "jwtToken不能为空")
+    @Schema(name = "jwtToken", description = "token")
+    String jwtToken;
+
+    @NotEmpty(message = "返回码不能为空")
+    @Schema(name = "code", description = "返回码")
+    String code;
+
+    public @NotEmpty(message = "jwtToken不能为空") String getJwtToken() {
+        return jwtToken;
+    }
+
+    public void setJwtToken(@NotEmpty(message = "jwtToken不能为空") String jwtToken) {
+        this.jwtToken = jwtToken;
+    }
+
+    public @NotEmpty(message = "返回码不能为空") String getCode() {
+        return code;
+    }
+
+    public void setCode(@NotEmpty(message = "返回码不能为空") String code) {
+        this.code = code;
+    }
+}

+ 61 - 0
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/ScanCode.java

@@ -0,0 +1,61 @@
+/*
+ * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.dromara.maxkey.authn;
+
+import jakarta.validation.constraints.NotEmpty;
+
+/**
+ * @description:
+ * @author: orangeBabu
+ * @time: 16/8/2024 PM4:28
+ */
+public class ScanCode {
+
+    @NotEmpty(message = "二维码内容不能为空")
+    String code;
+
+    @NotEmpty(message = "登录方式不能为空")
+    String authType;
+
+    @NotEmpty(message = "state不能为空")
+    String state;
+
+    public @NotEmpty(message = "二维码内容不能为空") String getCode() {
+        return code;
+    }
+
+    public void setCode(@NotEmpty(message = "二维码内容不能为空") String code) {
+        this.code = code;
+    }
+
+    public @NotEmpty(message = "登录方式不能为空") String getAuthType() {
+        return authType;
+    }
+
+    public void setAuthType(@NotEmpty(message = "登录方式不能为空") String authType) {
+        this.authType = authType;
+    }
+
+    public @NotEmpty(message = "state不能为空") String getState() {
+        return state;
+    }
+
+    public void setState(@NotEmpty(message = "state不能为空") String state) {
+        this.state = state;
+    }
+}

+ 1 - 1
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/SignPrincipal.java

@@ -21,7 +21,7 @@ import java.util.Collection;
 import java.util.List;
 
 import org.dromara.maxkey.authn.session.Session;
-import org.dromara.maxkey.entity.UserInfo;
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.userdetails.UserDetails;
 

+ 3 - 2
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/jwt/AuthJwtService.java

@@ -20,10 +20,11 @@ package org.dromara.maxkey.authn.jwt;
 import java.text.ParseException;
 import java.util.Date;
 
+import org.apache.commons.lang3.StringUtils;
 import org.dromara.maxkey.authn.SignPrincipal;
 import org.dromara.maxkey.crypto.jwt.HMAC512Service;
-import org.dromara.maxkey.entity.UserInfo;
-import org.dromara.maxkey.util.StringUtils;
+import org.dromara.maxkey.entity.idm.UserInfo;
+import org.dromara.maxkey.util.StrUtils;
 import org.dromara.maxkey.web.WebContext;
 import org.joda.time.DateTime;
 import org.slf4j.Logger;

+ 1 - 1
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/InMemorySessionManager.java

@@ -21,7 +21,7 @@ import java.time.LocalDateTime;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
-import org.dromara.maxkey.entity.HistoryLogin;
+import org.dromara.maxkey.entity.history.HistoryLogin;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 

+ 1 - 1
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/RedisSessionManager.java

@@ -20,7 +20,7 @@ package org.dromara.maxkey.authn.session;
 import java.time.LocalDateTime;
 import java.util.List;
 
-import org.dromara.maxkey.entity.HistoryLogin;
+import org.dromara.maxkey.entity.history.HistoryLogin;
 import org.dromara.maxkey.persistence.redis.RedisConnection;
 import org.dromara.maxkey.persistence.redis.RedisConnectionFactory;
 import org.slf4j.Logger;

+ 11 - 11
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/SessionManager.java

@@ -1,42 +1,42 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
+
 
 package org.dromara.maxkey.authn.session;
 
 import java.time.LocalDateTime;
 import java.util.List;
 
-import org.dromara.maxkey.entity.HistoryLogin;
+import org.dromara.maxkey.entity.history.HistoryLogin;
 
 public interface SessionManager {
 
 	public  void create(String sessionId, Session session);
 
     public  Session remove(String sessionId);
-    
+
     public  Session get(String sessionId);
-    
+
     public Session refresh(String sessionId ,LocalDateTime refreshTime);
-    
+
     public Session refresh(String sessionId);
-    
+
     public List<HistoryLogin> querySessions();
-    
+
     public int getValiditySeconds();
-    
+
     public void terminate(String sessionId,String userId,String username);
 }

+ 2 - 2
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/session/SessionManagerFactory.java

@@ -25,8 +25,8 @@ import java.util.Date;
 import java.util.List;
 
 import org.dromara.maxkey.constants.ConstsPersistence;
-import org.dromara.maxkey.entity.HistoryLogin;
-import org.dromara.maxkey.entity.UserInfo;
+import org.dromara.maxkey.entity.history.HistoryLogin;
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.dromara.maxkey.persistence.redis.RedisConnectionFactory;
 import org.dromara.maxkey.util.DateUtils;
 import org.slf4j.Logger;

+ 12 - 5
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/web/AuthTokenRefreshPoint.java

@@ -17,27 +17,28 @@
 
 package org.dromara.maxkey.authn.web;
 
+import org.apache.commons.lang3.StringUtils;
 import org.dromara.maxkey.authn.jwt.AuthJwt;
 import org.dromara.maxkey.authn.jwt.AuthRefreshTokenService;
 import org.dromara.maxkey.authn.jwt.AuthTokenService;
 import org.dromara.maxkey.authn.session.Session;
 import org.dromara.maxkey.authn.session.SessionManager;
 import org.dromara.maxkey.entity.Message;
-import org.dromara.maxkey.util.StringUtils;
 import org.dromara.maxkey.web.WebContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
 
 import jakarta.servlet.http.HttpServletRequest;
 
-@Controller
+@RestController
 @RequestMapping(value = "/auth")
 public class AuthTokenRefreshPoint {
 	private static final  Logger _logger = LoggerFactory.getLogger(AuthTokenRefreshPoint.class);
@@ -51,7 +52,13 @@ public class AuthTokenRefreshPoint {
 	@Autowired
 	SessionManager sessionManager;
 	
- 	@RequestMapping(value={"/token/refresh"}, produces = {MediaType.APPLICATION_JSON_VALUE})
+	@GetMapping(value={"/token/refresh"})
+	public ResponseEntity<?> refreshGet(HttpServletRequest request,
+			@RequestParam(name = "refresh_token", required = false) String refreshToken) {
+		return refresh(request,refreshToken);
+	}
+	
+ 	@PostMapping(value={"/token/refresh"})
 	public ResponseEntity<?> refresh(HttpServletRequest request,
 			@RequestParam(name = "refresh_token", required = false) String refreshToken) {
  		_logger.debug("try to refresh token " );

+ 32 - 23
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/web/AuthorizationUtils.java

@@ -1,30 +1,31 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
+
 
 package org.dromara.maxkey.authn.web;
 
 import java.text.ParseException;
 
 
+import com.nimbusds.jwt.SignedJWT;
 import org.dromara.maxkey.authn.SignPrincipal;
 import org.dromara.maxkey.authn.jwt.AuthTokenService;
 import org.dromara.maxkey.authn.session.Session;
 import org.dromara.maxkey.authn.session.SessionManager;
-import org.dromara.maxkey.entity.UserInfo;
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.dromara.maxkey.util.AuthorizationHeaderUtils;
 import org.dromara.maxkey.web.WebConstants;
 import org.dromara.maxkey.web.WebContext;
@@ -37,14 +38,14 @@ import jakarta.servlet.http.HttpServletRequest;
 
 public class AuthorizationUtils {
 	private static final Logger _logger = LoggerFactory.getLogger(AuthorizationUtils.class);
-	
+
 	public static final class BEARERTYPE{
-		
+
 		public static final String CONGRESS 		= "congress";
-		
+
 		public static final String AUTHORIZATION 	= "Authorization";
 	}
-	
+
 	public static  void authenticateWithCookie(
 			HttpServletRequest request,
 			AuthTokenService authTokenService,
@@ -55,12 +56,12 @@ public class AuthorizationUtils {
 	    	String  authorization =  authCookie.getValue();
 	    	_logger.trace("Try congress authenticate .");
 	    	doJwtAuthenticate(BEARERTYPE.CONGRESS,authorization,authTokenService,sessionManager);
-		}else {			
+		}else {
 			_logger.debug("cookie is null , clear authentication .");
 			clearAuthentication();
 		}
 	}
-	
+
 	public static  void authenticate(
 			HttpServletRequest request,
 			AuthTokenService authTokenService,
@@ -71,9 +72,9 @@ public class AuthorizationUtils {
 			_logger.trace("Try Authorization authenticate .");
 			doJwtAuthenticate(BEARERTYPE.AUTHORIZATION,authorization,authTokenService,sessionManager);
 		}
-		 
+
 	}
-	
+
 	public static void doJwtAuthenticate(
 			String  bearerType,
 			String  authorization,
@@ -99,17 +100,25 @@ public class AuthorizationUtils {
 		}
 	}
 
-    
+	public static Session getSession(SessionManager sessionManager, String authorization) throws ParseException {
+		_logger.debug("get session by authorization {}", authorization);
+		SignedJWT signedJWT = SignedJWT.parse(authorization);
+		String sessionId = signedJWT.getJWTClaimsSet().getJWTID();
+		_logger.debug("sessionId {}", sessionId);
+		return sessionManager.get(sessionId);
+	}
+
+
     public static Authentication getAuthentication() {
     	Authentication authentication = (Authentication) getAuthentication(WebContext.getRequest());
         return authentication;
     }
-    
+
     public static Authentication getAuthentication(HttpServletRequest request) {
     	Authentication authentication = (Authentication) request.getSession().getAttribute(WebConstants.AUTHENTICATION);
         return authentication;
     }
-    
+
     //set Authentication to http session
     public static void setAuthentication(Authentication authentication) {
     	WebContext.setAttribute(WebConstants.AUTHENTICATION, authentication);
@@ -118,24 +127,24 @@ public class AuthorizationUtils {
     public static void clearAuthentication() {
     	WebContext.removeAttribute(WebConstants.AUTHENTICATION);
     }
-    
+
     public static  boolean isAuthenticated() {
     	return getAuthentication() != null;
     }
-    
+
     public static  boolean isNotAuthenticated() {
     	return ! isAuthenticated();
     }
-    
+
     public static SignPrincipal getPrincipal() {
     	 Authentication authentication =  getAuthentication();
     	return getPrincipal(authentication);
     }
-    
+
     public static SignPrincipal getPrincipal(Authentication authentication) {
     	return authentication == null ? null : (SignPrincipal) authentication.getPrincipal();
    }
-    
+
     public static UserInfo getUserInfo(Authentication authentication) {
     	UserInfo userInfo = null;
     	SignPrincipal principal = getPrincipal(authentication);
@@ -144,9 +153,9 @@ public class AuthorizationUtils {
         }
     	return userInfo;
     }
-    
+
     public static UserInfo getUserInfo() {
     	return getUserInfo(getAuthentication());
     }
-	
+
 }

+ 1 - 1
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/web/CurrentUserMethodArgumentResolver.java

@@ -18,7 +18,7 @@
 package org.dromara.maxkey.authn.web;
 
 import org.dromara.maxkey.authn.annotation.CurrentUser;
-import org.dromara.maxkey.entity.UserInfo;
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.dromara.maxkey.web.WebConstants;
 import org.springframework.core.MethodParameter;
 import org.springframework.security.core.Authentication;

+ 5 - 6
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/web/FileUploadEndpoint.java

@@ -22,15 +22,14 @@ import java.io.IOException;
 import org.dromara.maxkey.authn.annotation.CurrentUser;
 import org.dromara.maxkey.entity.FileUpload;
 import org.dromara.maxkey.entity.Message;
-import org.dromara.maxkey.entity.UserInfo;
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.dromara.maxkey.persistence.service.FileUploadService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 
 import jakarta.servlet.http.HttpServletRequest;
@@ -44,9 +43,9 @@ public class FileUploadEndpoint {
 	@Autowired
 	FileUploadService fileUploadService;
 	
- 	@RequestMapping(value={"/file/upload/"})
+ 	@PostMapping({"/file/upload/"})
  	@ResponseBody
- 	public ResponseEntity<?> upload( HttpServletRequest request, 
+ 	public Message<Object> upload( HttpServletRequest request, 
  	                            HttpServletResponse response,
  	                           @ModelAttribute FileUpload fileUpload,
  	                           @CurrentUser UserInfo currentUser){
@@ -68,7 +67,7 @@ public class FileUploadEndpoint {
 				_logger.error("FileUpload IOException",e);
 			}
 		}
- 		return new Message<Object>(Message.SUCCESS,(Object)fileUpload.getId()).buildResponse();
+ 		return new Message<Object>(Message.SUCCESS,(Object)fileUpload.getId());
  	}
  	
 }

+ 9 - 10
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/authn/web/InstitutionEndpoint.java

@@ -25,22 +25,21 @@ import org.dromara.maxkey.persistence.repository.InstitutionsRepository;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestHeader;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 import jakarta.servlet.http.HttpServletRequest;
 
-@Controller
+@RestController
 @RequestMapping(value = "/inst")
 public class InstitutionEndpoint {
 	private static final  Logger _logger = LoggerFactory.getLogger(InstitutionEndpoint.class);
 	
-	public final static String  HEADER_HOST 		= "host";
+	public static final  String  HEADER_HOST 		= "host";
 	
-	public final static String  HEADER_HOSTNAME 	= "hostname";
+	public static final  String  HEADER_HOSTNAME 	= "hostname";
 	
 	@Autowired
 	InstitutionsRepository institutionsRepository;
@@ -48,8 +47,8 @@ public class InstitutionEndpoint {
 	@Autowired
 	ApplicationConfig applicationConfig;
 	
- 	@RequestMapping(value={"/get"}, produces = {MediaType.APPLICATION_JSON_VALUE})
-	public ResponseEntity<?> get(
+ 	@GetMapping(value={"/get"})
+	public Message<Institutions> get(
 			HttpServletRequest request,
 			@RequestHeader(value = "Origin",required=false) String originURL,
 			@RequestHeader(value = HEADER_HOSTNAME,required=false) String headerHostName,
@@ -76,11 +75,11 @@ public class InstitutionEndpoint {
 		Institutions inst = institutionsRepository.get(host);
 		if(inst != null) {
 			_logger.debug("inst {}",inst);
-			return new Message<Institutions>(inst).buildResponse();
+			return new Message<>(inst);
 		}else {
 			Institutions defaultInst = institutionsRepository.get("1");
 			_logger.debug("default inst {}",inst);
-			return new Message<Institutions>(defaultInst).buildResponse();
+			return new Message<>(defaultInst);
 		}
  	}
 }

+ 1 - 1
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/autoconfigure/MvcCurrentUserAutoConfiguration.java

@@ -40,7 +40,7 @@ public class MvcCurrentUserAutoConfiguration  implements WebMvcConfigurer {
     }
     
     @Bean
-    public CurrentUserMethodArgumentResolver currentUserMethodArgumentResolver() {
+    CurrentUserMethodArgumentResolver currentUserMethodArgumentResolver() {
         return new CurrentUserMethodArgumentResolver();
     }
     

+ 3 - 3
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/autoconfigure/SessionAutoConfiguration.java

@@ -37,13 +37,13 @@ public class SessionAutoConfiguration  {
     
     
     @Bean(name = "savedRequestSuccessHandler")
-    public SavedRequestAwareAuthenticationSuccessHandler 
+    SavedRequestAwareAuthenticationSuccessHandler 
             savedRequestAwareAuthenticationSuccessHandler() {
         return new SavedRequestAwareAuthenticationSuccessHandler();
     }
     
     @Bean
-    public SessionManager sessionManager(
+    SessionManager sessionManager(
             @Value("${maxkey.server.persistence}") int persistence,
             JdbcTemplate jdbcTemplate,
             RedisConnectionFactory redisConnFactory,
@@ -55,7 +55,7 @@ public class SessionAutoConfiguration  {
     }
 
     @Bean
-    public HttpSessionListenerAdapter httpSessionListenerAdapter() {
+    HttpSessionListenerAdapter httpSessionListenerAdapter() {
         return new HttpSessionListenerAdapter();
     }
     

+ 2 - 2
maxkey-authentications/maxkey-authentication-core/src/main/java/org/dromara/maxkey/autoconfigure/TokenAutoConfiguration.java

@@ -40,7 +40,7 @@ public class TokenAutoConfiguration{
             LoggerFactory.getLogger(TokenAutoConfiguration.class);
     
     @Bean
-    public AuthTokenService authTokenService(
+    AuthTokenService authTokenService(
     		AuthJwkConfig authJwkConfig,
     		RedisConnectionFactory redisConnFactory,
     		MomentaryService  momentaryService,
@@ -63,7 +63,7 @@ public class TokenAutoConfiguration{
     }
     
     @Bean
-    public AuthRefreshTokenService refreshTokenService(AuthJwkConfig authJwkConfig) throws JOSEException {
+    AuthRefreshTokenService refreshTokenService(AuthJwkConfig authJwkConfig) throws JOSEException {
     	return new AuthRefreshTokenService(authJwkConfig);
     }
     

+ 3 - 0
maxkey-authentications/maxkey-authentication-core/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -0,0 +1,3 @@
+org.dromara.maxkey.autoconfigure.MvcCurrentUserAutoConfiguration
+org.dromara.maxkey.autoconfigure.SessionAutoConfiguration
+org.dromara.maxkey.autoconfigure.TokenAutoConfiguration

+ 5 - 3
maxkey-authentications/maxkey-authentication-provider/build.gradle

@@ -9,9 +9,11 @@ dependencies {
 	implementation project(":maxkey-common")
 	implementation project(":maxkey-core")
 	implementation project(":maxkey-persistence")
+	
+	implementation project(":maxkey-starter:maxkey-starter-ip2location")
+	implementation project(":maxkey-starter:maxkey-starter-otp")
+	implementation project(":maxkey-starter:maxkey-starter-sms")
+	
 	implementation project(":maxkey-authentications:maxkey-authentication-core")
-	implementation project(":maxkey-authentications:maxkey-authentication-ip2location")
-	implementation project(":maxkey-authentications:maxkey-authentication-otp")
-	implementation project(":maxkey-authentications:maxkey-authentication-sms")
    
 }

+ 59 - 50
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/AbstractAuthenticationProvider.java

@@ -1,19 +1,19 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
+
 
 package org.dromara.maxkey.authn.provider;
 
@@ -30,7 +30,7 @@ import org.dromara.maxkey.authn.web.AuthorizationUtils;
 import org.dromara.maxkey.configuration.ApplicationConfig;
 import org.dromara.maxkey.constants.ConstsLoginType;
 import org.dromara.maxkey.constants.ConstsStatus;
-import org.dromara.maxkey.entity.UserInfo;
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.dromara.maxkey.password.onetimepwd.AbstractOtpAuthn;
 import org.dromara.maxkey.password.onetimepwd.MailOtpAuthnService;
 import org.dromara.maxkey.web.WebConstants;
@@ -45,37 +45,46 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
 import org.springframework.security.web.authentication.WebAuthenticationDetails;
 /**
  * login Authentication abstract class.
- * 
+ *
  * @author Crystal.Sea
  *
  */
 public abstract class AbstractAuthenticationProvider {
-    private static final Logger _logger = 
+    private static final Logger _logger =
             LoggerFactory.getLogger(AbstractAuthenticationProvider.class);
 
     public static String PROVIDER_SUFFIX = "AuthenticationProvider";
-    
+
     public class AuthType{
-    	public final static String NORMAL 	= "normal";
-    	public final static String TFA 		= "tfa";
-    	public final static String MOBILE 	= "mobile";
-    	public final static String TRUSTED 	= "trusted";
+    	public static final  String NORMAL 	= "normal";
+    	public static final  String TFA 		= "tfa";
+    	public static final  String MOBILE 	= "mobile";
+    	public static final  String TRUSTED 	= "trusted";
+        /**
+         * 扫描认证
+         */
+        public static final  String SCAN_CODE 	= "scancode";
+
+        /**
+         * 手机端APP
+         */
+        public static final  String APP 		= "app";
     }
-    
+
     protected ApplicationConfig applicationConfig;
 
     protected AbstractAuthenticationRealm authenticationRealm;
 
     protected AbstractOtpAuthn tfaOtpAuthn;
-    
+
     protected MailOtpAuthnService otpAuthnService;
 
     protected SessionManager sessionManager;
-    
+
     protected AuthTokenService authTokenService;
-    
+
     public static  ArrayList<GrantedAuthority> grantedAdministratorsAuthoritys = new ArrayList<GrantedAuthority>();
-    
+
     static {
         grantedAdministratorsAuthoritys.add(new SimpleGrantedAuthority("ROLE_ADMINISTRATORS"));
     }
@@ -83,7 +92,7 @@ public abstract class AbstractAuthenticationProvider {
     public abstract String getProviderName();
 
     public abstract Authentication doAuthenticate(LoginCredential authentication);
-    
+
     @SuppressWarnings("rawtypes")
     public boolean supports(Class authentication) {
         return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
@@ -92,13 +101,13 @@ public abstract class AbstractAuthenticationProvider {
     public Authentication authenticate(LoginCredential authentication){
     	return null;
     }
-    
+
     public Authentication authenticate(LoginCredential authentication,boolean trusted) {
     	return null;
     }
-    
+
     /**
-     * createOnlineSession 
+     * createOnlineSession
      * @param credential
      * @param userInfo
      * @return
@@ -112,7 +121,7 @@ public abstract class AbstractAuthenticationProvider {
 
         List<GrantedAuthority> grantedAuthoritys = authenticationRealm.grantAuthority(userInfo);
         principal.setAuthenticated(true);
-        
+
         for(GrantedAuthority administratorsAuthority : grantedAdministratorsAuthoritys) {
             if(grantedAuthoritys.contains(administratorsAuthority)) {
             	principal.setRoleAdministrators(true);
@@ -120,37 +129,37 @@ public abstract class AbstractAuthenticationProvider {
             }
         }
         _logger.debug("Granted Authority {}" , grantedAuthoritys);
-        
+
         principal.setGrantedAuthorityApps(authenticationRealm.queryAuthorizedApps(grantedAuthoritys));
-        
+
         UsernamePasswordAuthenticationToken authenticationToken =
                 new UsernamePasswordAuthenticationToken(
-                		principal, 
-                        "PASSWORD", 
+                		principal,
+                        "PASSWORD",
                         grantedAuthoritys
                 );
-        
+
         authenticationToken.setDetails(
                 new WebAuthenticationDetails(WebContext.getRequest()));
-        
+
         /*
          *  put Authentication to current session context
          */
         session.setAuthentication(authenticationToken);
-        
+
         //create session
         this.sessionManager.create(session.getId(), session);
-        
+
         //set Authentication to http session
         AuthorizationUtils.setAuthentication(authenticationToken);
-     
+
         return authenticationToken;
     }
-    
+
     /**
      * login user by j_username and j_cname first query user by j_cname if first
      * step userinfo is null,query user from system.
-     * 
+     *
      * @param username String
      * @param password String
      * @return
@@ -164,7 +173,7 @@ public abstract class AbstractAuthenticationProvider {
             } else {
                 _logger.debug("User Login. ");
             }
-            
+
         }
 
         return userInfo;
@@ -172,7 +181,7 @@ public abstract class AbstractAuthenticationProvider {
 
     /**
      * check input password empty.
-     * 
+     *
      * @param password String
      * @return
      */
@@ -185,7 +194,7 @@ public abstract class AbstractAuthenticationProvider {
 
     /**
      * check input username or password empty.
-     * 
+     *
      * @param email String
      * @return
      */
@@ -198,7 +207,7 @@ public abstract class AbstractAuthenticationProvider {
 
     /**
      * check input username empty.
-     * 
+     *
      * @param username String
      * @return
      */
@@ -219,8 +228,8 @@ public abstract class AbstractAuthenticationProvider {
             loginUser.setDisplayName("not exist");
             loginUser.setLoginCount(0);
             authenticationRealm.insertLoginHistory(
-            			loginUser, 
-            			ConstsLoginType.LOCAL, 
+            			loginUser,
+            			ConstsLoginType.LOCAL,
             			"",
             			i18nMessage,
             			WebConstants.LOGIN_RESULT.USER_NOT_EXIST);
@@ -228,22 +237,22 @@ public abstract class AbstractAuthenticationProvider {
         }
         return true;
     }
-    
+
     protected boolean statusValid(LoginCredential loginCredential , UserInfo userInfo) {
     	if(userInfo.getIsLocked()==ConstsStatus.LOCK) {
-    		authenticationRealm.insertLoginHistory( 
-    				userInfo, 
-                    loginCredential.getAuthType(), 
-                    loginCredential.getProvider(), 
-                    loginCredential.getCode(), 
+    		authenticationRealm.insertLoginHistory(
+    				userInfo,
+                    loginCredential.getAuthType(),
+                    loginCredential.getProvider(),
+                    loginCredential.getCode(),
                     WebConstants.LOGIN_RESULT.USER_LOCKED
                 );
     	}else if(userInfo.getStatus()!=ConstsStatus.ACTIVE) {
-    		authenticationRealm.insertLoginHistory( 
-    				userInfo, 
-                    loginCredential.getAuthType(), 
-                    loginCredential.getProvider(), 
-                    loginCredential.getCode(), 
+    		authenticationRealm.insertLoginHistory(
+    				userInfo,
+                    loginCredential.getAuthType(),
+                    loginCredential.getProvider(),
+                    loginCredential.getCode(),
                     WebConstants.LOGIN_RESULT.USER_INACTIVE
                 );
     	}

+ 130 - 0
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/impl/AppAuthenticationProvider.java

@@ -0,0 +1,130 @@
+/*
+ * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.dromara.maxkey.authn.provider.impl;
+
+import org.dromara.maxkey.authn.LoginCredential;
+import org.dromara.maxkey.authn.jwt.AuthTokenService;
+import org.dromara.maxkey.authn.provider.AbstractAuthenticationProvider;
+import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
+import org.dromara.maxkey.authn.session.SessionManager;
+import org.dromara.maxkey.configuration.ApplicationConfig;
+import org.dromara.maxkey.constants.ConstsLoginType;
+import org.dromara.maxkey.entity.idm.UserInfo;
+import org.dromara.maxkey.web.WebConstants;
+import org.dromara.maxkey.web.WebContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+
+/**
+ * @description:
+ * @author: orangeBabu
+ * @time: 19/8/2024 PM3:41
+ */
+public class AppAuthenticationProvider extends AbstractAuthenticationProvider {
+    private static final Logger _logger = LoggerFactory.getLogger(AppAuthenticationProvider.class);
+
+    public AppAuthenticationProvider() {
+        super();
+    }
+
+    public AppAuthenticationProvider(
+            AbstractAuthenticationRealm authenticationRealm,
+            ApplicationConfig applicationConfig,
+            SessionManager sessionManager,
+            AuthTokenService authTokenService) {
+        this.authenticationRealm = authenticationRealm;
+        this.applicationConfig = applicationConfig;
+        this.sessionManager = sessionManager;
+        this.authTokenService = authTokenService;
+    }
+
+
+    @Override
+    public String getProviderName() {
+        return "app" + PROVIDER_SUFFIX;
+    }
+
+    @Override
+    public Authentication doAuthenticate(LoginCredential loginCredential) {
+        UsernamePasswordAuthenticationToken authenticationToken = null;
+        _logger.debug("Trying to authenticate user '{}' via {}",
+                loginCredential.getPrincipal(), getProviderName());
+        try {
+
+            _logger.debug("authentication {}", loginCredential);
+
+            if(this.applicationConfig.getLoginConfig().isCaptcha()) {
+                captchaValid(loginCredential.getState(),loginCredential.getCaptcha());
+            }
+
+            emptyPasswordValid(loginCredential.getPassword());
+
+            emptyUsernameValid(loginCredential.getUsername());
+
+            //查询用户
+            UserInfo userInfo = loadUserInfo(loginCredential.getUsername(), loginCredential.getPassword());
+
+            //Validate PasswordPolicy
+            authenticationRealm.getPasswordPolicyValidator().passwordPolicyValid(userInfo);
+
+            statusValid(loginCredential, userInfo);
+
+            //Match password
+            authenticationRealm.passwordMatches(userInfo, loginCredential.getPassword());
+
+            //apply PasswordSetType and resetBadPasswordCount
+            authenticationRealm.getPasswordPolicyValidator().applyPasswordPolicy(userInfo);
+
+            authenticationToken = createOnlineTicket(loginCredential, userInfo);
+            // user authenticated
+            _logger.debug("'{}' authenticated successfully by {}.",
+                    loginCredential.getPrincipal(), getProviderName());
+
+            authenticationRealm.insertLoginHistory(userInfo,
+                    ConstsLoginType.LOCAL,
+                    "",
+                    "xe00000004",
+                    WebConstants.LOGIN_RESULT.SUCCESS);
+
+        } catch (
+                AuthenticationException e) {
+            _logger.error("Failed to authenticate user {} via {}: {}",
+                    loginCredential.getPrincipal(),
+                    getProviderName(),
+                    e.getMessage());
+            WebContext.setAttribute(
+                    WebConstants.LOGIN_ERROR_SESSION_MESSAGE, e.getMessage());
+        } catch (Exception e) {
+            _logger.error("Login error Unexpected exception in {} authentication:\n{}",
+                    getProviderName(), e.getMessage());
+        }
+
+        return authenticationToken;
+    }
+
+    protected void captchaValid(String state ,String captcha) {
+        // for basic
+        if(!authTokenService.validateCaptcha(state,captcha)) {
+            throw new BadCredentialsException(WebContext.getI18nValue("login.error.captcha"));
+        }
+    }
+}

+ 3 - 5
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/impl/MfaAuthenticationProvider.java

@@ -25,7 +25,7 @@ import org.dromara.maxkey.authn.session.SessionManager;
 import org.dromara.maxkey.configuration.ApplicationConfig;
 import org.dromara.maxkey.constants.ConstsLoginType;
 import org.dromara.maxkey.entity.Institutions;
-import org.dromara.maxkey.entity.UserInfo;
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.dromara.maxkey.web.WebConstants;
 import org.dromara.maxkey.web.WebContext;
 import org.slf4j.Logger;
@@ -72,10 +72,8 @@ public class MfaAuthenticationProvider extends AbstractAuthenticationProvider {
                 loginCredential.getPrincipal(), getProviderName());
         try {
         	
-	        _logger.debug("authentication " + loginCredential);
-	        
-	        Institutions inst = (Institutions)WebContext.getAttribute(WebConstants.CURRENT_INST);
-
+	        _logger.debug("authentication {}" , loginCredential);
+	       
 	        emptyPasswordValid(loginCredential.getPassword());
 	
 	        UserInfo userInfo = null;

+ 1 - 1
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/impl/MobileAuthenticationProvider.java

@@ -23,7 +23,7 @@ import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
 import org.dromara.maxkey.authn.session.SessionManager;
 import org.dromara.maxkey.configuration.ApplicationConfig;
 import org.dromara.maxkey.constants.ConstsLoginType;
-import org.dromara.maxkey.entity.UserInfo;
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.dromara.maxkey.password.onetimepwd.AbstractOtpAuthn;
 import org.dromara.maxkey.password.sms.SmsOtpAuthnService;
 import org.dromara.maxkey.web.WebConstants;

+ 5 - 12
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/impl/NormalAuthenticationProvider.java

@@ -26,8 +26,7 @@ import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
 import org.dromara.maxkey.authn.session.SessionManager;
 import org.dromara.maxkey.configuration.ApplicationConfig;
 import org.dromara.maxkey.constants.ConstsLoginType;
-import org.dromara.maxkey.entity.Institutions;
-import org.dromara.maxkey.entity.UserInfo;
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.dromara.maxkey.web.WebConstants;
 import org.dromara.maxkey.web.WebContext;
 import org.slf4j.Logger;
@@ -73,16 +72,10 @@ public class NormalAuthenticationProvider extends AbstractAuthenticationProvider
                 loginCredential.getPrincipal(), getProviderName());
         try {
         	
-	        _logger.debug("authentication " + loginCredential);
-	        
-	        Institutions inst = (Institutions)WebContext.getAttribute(WebConstants.CURRENT_INST);
+	        _logger.debug("authentication {}" , loginCredential);
 	        
 	        if(this.applicationConfig.getLoginConfig().isCaptcha()) {
 	        	captchaValid(loginCredential.getState(),loginCredential.getCaptcha());
-	        	
-	        }else if(!inst.getCaptcha().equalsIgnoreCase("NONE")) {
-	        	
-	        	captchaValid(loginCredential.getState(),loginCredential.getCaptcha());
 	        }
 	
 	        emptyPasswordValid(loginCredential.getPassword());
@@ -116,9 +109,9 @@ public class NormalAuthenticationProvider extends AbstractAuthenticationProvider
 									                WebConstants.LOGIN_RESULT.SUCCESS);
         } catch (AuthenticationException e) {
             _logger.error("Failed to authenticate user {} via {}: {}",
-                    new Object[] {  loginCredential.getPrincipal(),
+                    				loginCredential.getPrincipal(),
                                     getProviderName(),
-                                    e.getMessage() });
+                                    e.getMessage() );
             WebContext.setAttribute(
                     WebConstants.LOGIN_ERROR_SESSION_MESSAGE, e.getMessage());
         } catch (Exception e) {
@@ -136,7 +129,7 @@ public class NormalAuthenticationProvider extends AbstractAuthenticationProvider
      * @param captcha String
      * @throws ParseException 
      */
-    protected void captchaValid(String state ,String captcha) throws ParseException {
+    protected void captchaValid(String state ,String captcha) {
         // for basic
     	if(!authTokenService.validateCaptcha(state,captcha)) {
     		throw new BadCredentialsException(WebContext.getI18nValue("login.error.captcha"));

+ 104 - 0
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/impl/ScanCodeAuthenticationProvider.java

@@ -0,0 +1,104 @@
+/*
+ * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.dromara.maxkey.authn.provider.impl;
+
+import org.dromara.maxkey.authn.LoginCredential;
+import org.dromara.maxkey.authn.SignPrincipal;
+import org.dromara.maxkey.authn.provider.AbstractAuthenticationProvider;
+import org.dromara.maxkey.authn.provider.scancode.ScanCodeService;
+import org.dromara.maxkey.authn.provider.scancode.ScanCodeState;
+
+import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
+import org.dromara.maxkey.authn.session.SessionManager;
+
+import org.dromara.maxkey.constants.ConstsLoginType;
+import org.dromara.maxkey.crypto.password.PasswordReciprocal;
+import org.dromara.maxkey.entity.idm.UserInfo;
+import org.dromara.maxkey.web.WebConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+
+import java.util.Objects;
+
+/**
+ * @description:
+ * @author: orangeBabu
+ * @time: 16/8/2024 PM4:54
+ */
+public class ScanCodeAuthenticationProvider extends AbstractAuthenticationProvider {
+
+    private static final Logger _logger = LoggerFactory.getLogger(ScanCodeAuthenticationProvider.class);
+
+    @Autowired
+    ScanCodeService scanCodeService;
+
+    public ScanCodeAuthenticationProvider() {
+        super();
+    }
+
+    public ScanCodeAuthenticationProvider(
+            AbstractAuthenticationRealm authenticationRealm,
+            SessionManager sessionManager) {
+        this.authenticationRealm = authenticationRealm;
+        this.sessionManager = sessionManager;
+    }
+
+    @Override
+    public String getProviderName() {
+        return "scancode" + PROVIDER_SUFFIX;
+    }
+
+    @Override
+    public Authentication doAuthenticate(LoginCredential loginCredential) {
+        UsernamePasswordAuthenticationToken authenticationToken = null;
+
+        String encodeTicket = PasswordReciprocal.getInstance().decoder(loginCredential.getUsername());
+
+        ScanCodeState scanCodeState = scanCodeService.consume(encodeTicket);
+
+        if (Objects.isNull(scanCodeState)) {
+            return null;
+        }
+
+        SignPrincipal signPrincipal = (SignPrincipal) sessionManager.get(scanCodeState.getSessionId()).getAuthentication().getPrincipal();
+        //获取用户信息
+        UserInfo userInfo = signPrincipal.getUserInfo();
+
+        isUserExist(loginCredential , userInfo);
+
+        statusValid(loginCredential , userInfo);
+
+
+        //创建登录会话
+        authenticationToken = createOnlineTicket(loginCredential,userInfo);
+        // user authenticated
+        _logger.debug("'{}' authenticated successfully by {}.",
+                loginCredential.getPrincipal(), getProviderName());
+
+        authenticationRealm.insertLoginHistory(userInfo,
+                ConstsLoginType.LOCAL,
+                "",
+                "xe00000004",
+                WebConstants.LOGIN_RESULT.SUCCESS);
+
+        return  authenticationToken;
+    }
+}

+ 1 - 1
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/impl/TrustedAuthenticationProvider.java

@@ -22,7 +22,7 @@ import org.dromara.maxkey.authn.provider.AbstractAuthenticationProvider;
 import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
 import org.dromara.maxkey.authn.session.SessionManager;
 import org.dromara.maxkey.configuration.ApplicationConfig;
-import org.dromara.maxkey.entity.UserInfo;
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.dromara.maxkey.web.WebContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

+ 123 - 0
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/scancode/ScanCodeService.java

@@ -0,0 +1,123 @@
+/*
+ * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.dromara.maxkey.authn.provider.scancode;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.dromara.maxkey.authn.session.Session;
+import org.dromara.maxkey.authn.session.SessionManager;
+import org.dromara.maxkey.exception.BusinessException;
+import org.dromara.maxkey.persistence.cache.MomentaryService;
+import org.dromara.maxkey.util.IdGenerator;
+import org.dromara.maxkey.util.JsonUtils;
+import org.dromara.maxkey.util.TimeJsonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+import java.time.Duration;
+import java.util.Objects;
+
+/**
+ * @description:
+ * @author: orangeBabu
+ * @time: 15/8/2024 AM9:49
+ */
+
+@Repository
+public class ScanCodeService {
+    private static final Logger _logger = LoggerFactory.getLogger(ScanCodeService.class);
+
+    static final String SCANCODE_TICKET = "login:scancode:%s";
+
+    static final String SCANCODE_CONFIRM = "login:scancode:confirm:%s";
+
+    public static class STATE {
+        public static final String SCANED = "scaned";
+        public static final String CONFIRMED = "confirmed";
+        public static final String CANCELED = "canceled";
+
+        public static final String CANCEL = "cancel";
+        public static final String CONFIRM = "confirm";
+    }
+
+    int validitySeconds = 60 * 3; //default 3 minutes.
+
+    int cancelValiditySeconds = 60 * 1; //default 1 minutes.
+
+
+    @Autowired
+    IdGenerator idGenerator;
+
+    @Autowired
+    MomentaryService momentaryService;
+
+    private String getKey(String ticket) {
+        return SCANCODE_TICKET.formatted(ticket);
+    }
+
+    private String getConfirmKey(Long sessionId) {
+        return SCANCODE_CONFIRM.formatted(sessionId);
+    }
+
+    public String createTicket() {
+        String ticket = idGenerator.generate();
+        ScanCodeState scanCodeState = new ScanCodeState();
+        scanCodeState.setState("unscanned");
+
+        // 将对象序列化为 JSON 字符串
+        String jsonString = TimeJsonUtils.gsonToString(scanCodeState);
+        momentaryService.put(getKey(ticket), "", jsonString);
+        _logger.info("Ticket {} , Duration {}", ticket, jsonString);
+
+        return ticket;
+    }
+
+    public boolean validateTicket(String ticket, Session session) {
+        String key = getKey(ticket);
+        Object value = momentaryService.get(key, "");
+        if (Objects.isNull(value)) {
+            return false;
+        }
+
+        ScanCodeState scanCodeState = new ScanCodeState();
+        scanCodeState.setState("scanned");
+        scanCodeState.setTicket(ticket);
+        scanCodeState.setSessionId(session.getId());
+        momentaryService.put(key, "", TimeJsonUtils.gsonToString(scanCodeState));
+
+        return true;
+    }
+
+    public ScanCodeState consume(String ticket){
+        String key = getKey(ticket);
+        Object o = momentaryService.get(key, "");
+        if (Objects.nonNull(o)) {
+            String redisObject = o.toString();
+            ScanCodeState scanCodeState = TimeJsonUtils.gsonStringToObject(redisObject, ScanCodeState.class);
+            if ("scanned".equals(scanCodeState.getState())) {
+                momentaryService.remove(key, "");
+                return scanCodeState;
+            } else {
+                return null;
+            }
+        } else {
+            throw new BusinessException(20004, "该二维码失效");
+        }
+    }
+}

+ 70 - 0
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/scancode/ScanCodeState.java

@@ -0,0 +1,70 @@
+/*
+ * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.dromara.maxkey.authn.provider.scancode;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import org.dromara.maxkey.authn.session.Session;
+
+/**
+ * @description:
+ * @author: orangeBabu
+ * @time: 16/8/2024 PM5:42
+ */
+public class ScanCodeState {
+
+    String sessionId;
+
+    String ticket;
+
+    @JsonFormat(shape = JsonFormat.Shape.STRING)
+    Long confirmKey;
+
+    String state;
+
+    public String getSessionId() {
+        return sessionId;
+    }
+
+    public void setSessionId(String sessionId) {
+        this.sessionId = sessionId;
+    }
+
+    public String getTicket() {
+        return ticket;
+    }
+
+    public void setTicket(String ticket) {
+        this.ticket = ticket;
+    }
+
+    public Long getConfirmKey() {
+        return confirmKey;
+    }
+
+    public void setConfirmKey(Long confirmKey) {
+        this.confirmKey = confirmKey;
+    }
+
+    public String getState() {
+        return state;
+    }
+
+    public void setState(String state) {
+        this.state = state;
+    }
+}

+ 36 - 0
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/provider/scancode/ScancodeSignInfo.java

@@ -0,0 +1,36 @@
+/*
+ * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.dromara.maxkey.authn.provider.scancode;
+
+/**
+ * @description:
+ * @author: orangeBabu
+ * @time: 17/8/2024 PM5:08
+ */
+public class ScancodeSignInfo {
+
+    String username;
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+}

+ 3 - 3
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/realm/AbstractAuthenticationRealm.java

@@ -22,9 +22,9 @@ import java.util.List;
 
 import org.dromara.maxkey.authn.SignPrincipal;
 import org.dromara.maxkey.authn.realm.ldap.LdapAuthenticationRealmService;
-import org.dromara.maxkey.entity.Groups;
-import org.dromara.maxkey.entity.HistoryLogin;
-import org.dromara.maxkey.entity.UserInfo;
+import org.dromara.maxkey.entity.history.HistoryLogin;
+import org.dromara.maxkey.entity.idm.Groups;
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.dromara.maxkey.ip2location.IpLocationParser;
 import org.dromara.maxkey.ip2location.Region;
 import org.dromara.maxkey.persistence.repository.LoginHistoryRepository;

+ 3 - 3
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/realm/jdbc/JdbcAuthenticationRealm.java

@@ -23,8 +23,8 @@ import org.dromara.maxkey.authn.realm.ldap.LdapAuthenticationRealmService;
 import org.dromara.maxkey.constants.ConstsLoginType;
 import org.dromara.maxkey.constants.ConstsStatus;
 import org.dromara.maxkey.entity.ChangePassword;
-import org.dromara.maxkey.entity.PasswordPolicy;
-import org.dromara.maxkey.entity.UserInfo;
+import org.dromara.maxkey.entity.cnf.CnfPasswordPolicy;
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.dromara.maxkey.ip2location.IpLocationParser;
 import org.dromara.maxkey.persistence.repository.LoginHistoryRepository;
 import org.dromara.maxkey.persistence.repository.LoginRepository;
@@ -128,7 +128,7 @@ public class JdbcAuthenticationRealm extends AbstractAuthenticationRealm {
         if (!passwordMatches) {
             passwordPolicyValidator.plusBadPasswordCount(userInfo);
             insertLoginHistory(userInfo, ConstsLoginType.LOCAL, "", "xe00000004", WebConstants.LOGIN_RESULT.PASSWORD_ERROE);
-            PasswordPolicy passwordPolicy = passwordPolicyValidator.getPasswordPolicyRepository().getPasswordPolicy();
+            CnfPasswordPolicy passwordPolicy = passwordPolicyValidator.getPasswordPolicyRepository().getPasswordPolicy();
             if(userInfo.getBadPasswordCount()>=(passwordPolicy.getAttempts()/2)) {
                 throw new BadCredentialsException(
                         WebContext.getI18nValue("login.error.password.attempts",

+ 1 - 1
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/realm/ldap/ActiveDirectoryServer.java

@@ -30,7 +30,7 @@ import org.slf4j.LoggerFactory;
  *
  */
 public final class ActiveDirectoryServer implements IAuthenticationServer {
-	private final static Logger _logger = LoggerFactory.getLogger(ActiveDirectoryServer.class);
+	private static final  Logger _logger = LoggerFactory.getLogger(ActiveDirectoryServer.class);
 
 	ActiveDirectoryUtils activeDirectoryUtils;
 

+ 2 - 2
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/realm/ldap/LdapAuthenticationRealm.java

@@ -21,7 +21,7 @@ import java.util.List;
 
 import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
 import org.dromara.maxkey.authn.realm.IAuthenticationServer;
-import org.dromara.maxkey.entity.UserInfo;
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.jdbc.core.JdbcTemplate;
@@ -30,7 +30,7 @@ import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.Size;
 
 public class LdapAuthenticationRealm  extends AbstractAuthenticationRealm{
-	private final static Logger _logger = LoggerFactory.getLogger(LdapAuthenticationRealm.class);
+	private static final  Logger _logger = LoggerFactory.getLogger(LdapAuthenticationRealm.class);
 	
 	@NotNull
     @Size(min=1)

+ 6 - 6
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/realm/ldap/LdapAuthenticationRealmService.java

@@ -22,10 +22,10 @@ import java.util.concurrent.TimeUnit;
 
 import org.dromara.maxkey.authn.realm.IAuthenticationServer;
 import org.dromara.maxkey.crypto.password.PasswordReciprocal;
-import org.dromara.maxkey.entity.LdapContext;
+import org.dromara.maxkey.entity.cnf.CnfLdapContext;
 import org.dromara.maxkey.ldap.ActiveDirectoryUtils;
 import org.dromara.maxkey.ldap.LdapUtils;
-import org.dromara.maxkey.persistence.service.LdapContextService;
+import org.dromara.maxkey.persistence.service.CnfLdapContextService;
 
 import com.github.benmanes.caffeine.cache.Cache;
 import com.github.benmanes.caffeine.cache.Caffeine;
@@ -36,23 +36,23 @@ public class LdapAuthenticationRealmService {
                 .expireAfterWrite(60, TimeUnit.MINUTES)
                 .build();
     
-    LdapContextService ldapContextService;
+    CnfLdapContextService ldapContextService;
     
     
-    public LdapAuthenticationRealmService(LdapContextService ldapContextService) {
+    public LdapAuthenticationRealmService(CnfLdapContextService ldapContextService) {
 		this.ldapContextService = ldapContextService;
 	}
 
 	public LdapAuthenticationRealm getByInstId(String instId) {
 		LdapAuthenticationRealm authenticationRealm = ldapRealmStore.getIfPresent(instId);
 		if(authenticationRealm == null) {
-			List<LdapContext> ldapContexts = 
+			List<CnfLdapContext> ldapContexts = 
 					ldapContextService.find("where instid = ? and status = 1 ", new Object[]{instId}, new int[]{Types.VARCHAR});
 			authenticationRealm = new LdapAuthenticationRealm(false);
 			if(ldapContexts != null && ldapContexts.size()>0) {
 				authenticationRealm.setLdapSupport(true);
 				List<IAuthenticationServer> ldapAuthenticationServers = new ArrayList<IAuthenticationServer>();
-				for(LdapContext ldapContext : ldapContexts) { 
+				for(CnfLdapContext ldapContext : ldapContexts) { 
 					if(ldapContext.getProduct().equalsIgnoreCase("ActiveDirectory")) {
 						ActiveDirectoryServer ldapServer = new ActiveDirectoryServer();
 			            ActiveDirectoryUtils  ldapUtils  = new ActiveDirectoryUtils(

+ 1 - 1
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/realm/ldap/StandardLdapServer.java

@@ -35,7 +35,7 @@ import org.slf4j.LoggerFactory;
  *
  */
 public final class StandardLdapServer implements IAuthenticationServer {
-	private final static Logger _logger = LoggerFactory.getLogger(StandardLdapServer.class);
+	private static final  Logger _logger = LoggerFactory.getLogger(StandardLdapServer.class);
 	
 	LdapUtils ldapUtils;
 	

+ 7 - 6
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/support/jwt/HttpJwtEntryPoint.java

@@ -22,6 +22,7 @@ import org.dromara.maxkey.authn.jwt.AuthTokenService;
 import org.dromara.maxkey.authn.provider.AbstractAuthenticationProvider;
 import org.dromara.maxkey.configuration.ApplicationConfig;
 import org.dromara.maxkey.constants.ConstsLoginType;
+import org.dromara.maxkey.entity.Institutions;
 import org.dromara.maxkey.entity.Message;
 import org.dromara.maxkey.web.WebConstants;
 import org.slf4j.Logger;
@@ -54,7 +55,7 @@ public class HttpJwtEntryPoint {
 	JwtLoginService jwtLoginService;
 	
 	@RequestMapping(value={"/jwt"}, produces = {MediaType.APPLICATION_JSON_VALUE})
-	public ResponseEntity<?> jwt(@RequestParam(value = WebConstants.JWT_TOKEN_PARAMETER, required = true) String jwt) {
+	public Message<AuthJwt> jwt(@RequestParam(value = WebConstants.JWT_TOKEN_PARAMETER, required = true) String jwt) {
 		try {
 			//for jwt Login
 			 _logger.debug("jwt : " + jwt);
@@ -67,13 +68,13 @@ public class HttpJwtEntryPoint {
 				 Authentication  authentication = authenticationProvider.authenticate(loginCredential,true);
 				 _logger.debug("JWT Logined in , username " + username);
 				 AuthJwt authJwt = authTokenService.genAuthJwt(authentication);
-		 		 return new Message<AuthJwt>(authJwt).buildResponse();
+		 		 return new Message<AuthJwt>(authJwt);
 			 }
 		}catch(Exception e) {
 			_logger.error("Exception ",e);
 		}
 		
-		 return new Message<AuthJwt>(Message.FAIL).buildResponse();
+		 return new Message<AuthJwt>(Message.FAIL);
 	}
 	
 	/**
@@ -82,7 +83,7 @@ public class HttpJwtEntryPoint {
 	 * @return
 	 */
 	@RequestMapping(value={"/jwt/trust"}, produces = {MediaType.APPLICATION_JSON_VALUE})
-	public ResponseEntity<?> jwtTrust(@RequestParam(value = WebConstants.JWT_TOKEN_PARAMETER, required = true) String jwt) {
+	public Message<AuthJwt> jwtTrust(@RequestParam(value = WebConstants.JWT_TOKEN_PARAMETER, required = true) String jwt) {
 		try {
 			//for jwt Login
 			 _logger.debug("jwt : " + jwt);
@@ -93,13 +94,13 @@ public class HttpJwtEntryPoint {
 				 Authentication  authentication = authenticationProvider.authenticate(loginCredential,true);
 				 _logger.debug("JWT Logined in , username " + username);
 				 AuthJwt authJwt = authTokenService.genAuthJwt(authentication);
-		 		 return new Message<AuthJwt>(authJwt).buildResponse();
+		 		 return new Message<AuthJwt>(authJwt);
 			 }
 		}catch(Exception e) {
 			_logger.error("Exception ",e);
 		}
 		
-		 return new Message<AuthJwt>(Message.FAIL).buildResponse();
+		 return new Message<AuthJwt>(Message.FAIL);
 	}
 
 

+ 1 - 1
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/support/rememberme/AbstractRemeberMeManager.java

@@ -24,7 +24,7 @@ import org.dromara.maxkey.authn.SignPrincipal;
 import org.dromara.maxkey.authn.jwt.AuthTokenService;
 import org.dromara.maxkey.configuration.ApplicationConfig;
 import org.dromara.maxkey.crypto.jwt.HMAC512Service;
-import org.dromara.maxkey.entity.UserInfo;
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.dromara.maxkey.util.DateUtils;
 import org.dromara.maxkey.web.WebContext;
 import org.joda.time.DateTime;

+ 2 - 1
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/support/wsfederation/HttpWsFederationEntryPoint.java

@@ -18,12 +18,13 @@
 package org.dromara.maxkey.authn.support.wsfederation;
 
 
+import org.apache.commons.lang3.StringUtils;
 import org.dromara.maxkey.authn.LoginCredential;
 import org.dromara.maxkey.authn.provider.AbstractAuthenticationProvider;
 import org.dromara.maxkey.authn.web.AuthorizationUtils;
 import org.dromara.maxkey.configuration.ApplicationConfig;
 import org.dromara.maxkey.constants.ConstsLoginType;
-import org.dromara.maxkey.util.StringUtils;
+import org.dromara.maxkey.util.StrUtils;
 import org.opensaml.saml1.core.impl.AssertionImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

+ 1 - 1
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/authn/support/wsfederation/WsFederationServiceImpl.java

@@ -22,7 +22,7 @@ import org.slf4j.LoggerFactory;
 
 
 public class WsFederationServiceImpl implements   WsFederationService{
-	final static Logger _logger = LoggerFactory.getLogger(WsFederationServiceImpl.class);
+	static final  Logger _logger = LoggerFactory.getLogger(WsFederationServiceImpl.class);
 	
 	private WsFederationConfiguration wsFederationConfiguration;
 

+ 47 - 19
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/autoconfigure/AuthnProviderAutoConfiguration.java

@@ -1,28 +1,26 @@
 /*
  * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
+
 
 package org.dromara.maxkey.autoconfigure;
 
 import org.dromara.maxkey.authn.jwt.AuthTokenService;
 import org.dromara.maxkey.authn.provider.AbstractAuthenticationProvider;
 import org.dromara.maxkey.authn.provider.AuthenticationProviderFactory;
-import org.dromara.maxkey.authn.provider.impl.MobileAuthenticationProvider;
-import org.dromara.maxkey.authn.provider.impl.NormalAuthenticationProvider;
-import org.dromara.maxkey.authn.provider.impl.TrustedAuthenticationProvider;
+import org.dromara.maxkey.authn.provider.impl.*;
 import org.dromara.maxkey.authn.realm.AbstractAuthenticationRealm;
 import org.dromara.maxkey.authn.session.SessionManager;
 import org.dromara.maxkey.authn.support.rememberme.AbstractRemeberMeManager;
@@ -44,23 +42,27 @@ import org.springframework.jdbc.core.JdbcTemplate;
 @AutoConfiguration
 public class AuthnProviderAutoConfiguration {
     static final  Logger _logger = LoggerFactory.getLogger(AuthnProviderAutoConfiguration.class);
-    
+
     @Bean
-    public AbstractAuthenticationProvider authenticationProvider(
+     AbstractAuthenticationProvider authenticationProvider(
     		NormalAuthenticationProvider normalAuthenticationProvider,
     		MobileAuthenticationProvider mobileAuthenticationProvider,
-    		TrustedAuthenticationProvider trustedAuthenticationProvider
+    		TrustedAuthenticationProvider trustedAuthenticationProvider,
+			ScanCodeAuthenticationProvider scanCodeAuthenticationProvider,
+			AppAuthenticationProvider appAuthenticationProvider
     		) {
     	AuthenticationProviderFactory authenticationProvider = new AuthenticationProviderFactory();
     	authenticationProvider.addAuthenticationProvider(normalAuthenticationProvider);
     	authenticationProvider.addAuthenticationProvider(mobileAuthenticationProvider);
     	authenticationProvider.addAuthenticationProvider(trustedAuthenticationProvider);
-    	
+    	authenticationProvider.addAuthenticationProvider(scanCodeAuthenticationProvider);
+    	authenticationProvider.addAuthenticationProvider(appAuthenticationProvider);
+
     	return authenticationProvider;
     }
-    		
+
     @Bean
-    public NormalAuthenticationProvider normalAuthenticationProvider(
+    NormalAuthenticationProvider normalAuthenticationProvider(
     		AbstractAuthenticationRealm authenticationRealm,
     		ApplicationConfig applicationConfig,
     	    SessionManager sessionManager,
@@ -74,7 +76,33 @@ public class AuthnProviderAutoConfiguration {
         		authTokenService
         	);
     }
-    
+
+	@Bean
+	public ScanCodeAuthenticationProvider scanCodeAuthenticationProvider(
+			AbstractAuthenticationRealm authenticationRealm,
+			SessionManager sessionManager
+	) {
+		return new ScanCodeAuthenticationProvider(
+				authenticationRealm,
+				sessionManager
+		);
+	}
+
+	@Bean
+	public AppAuthenticationProvider appAuthenticationProvider(
+			AbstractAuthenticationRealm authenticationRealm,
+			ApplicationConfig applicationConfig,
+			SessionManager sessionManager,
+			AuthTokenService authTokenService
+	) {
+		return new AppAuthenticationProvider(
+				authenticationRealm,
+				applicationConfig,
+				sessionManager,
+				authTokenService
+		);
+	}
+
     @Bean
     public MobileAuthenticationProvider mobileAuthenticationProvider(
     		AbstractAuthenticationRealm authenticationRealm,
@@ -104,22 +132,22 @@ public class AuthnProviderAutoConfiguration {
         		sessionManager
         	);
     }
-    
+
     @Bean
     public PasswordPolicyValidator passwordPolicyValidator(JdbcTemplate jdbcTemplate,MessageSource messageSource) {
         return new PasswordPolicyValidator(jdbcTemplate,messageSource);
     }
-    
+
     @Bean
     public LoginRepository loginRepository(JdbcTemplate jdbcTemplate) {
         return new LoginRepository(jdbcTemplate);
     }
-    
+
     @Bean
     public LoginHistoryRepository loginHistoryRepository(JdbcTemplate jdbcTemplate) {
         return new LoginHistoryRepository(jdbcTemplate);
     }
-    
+
     /**
      * remeberMeService .
      * @return
@@ -135,5 +163,5 @@ public class AuthnProviderAutoConfiguration {
         return new  JdbcRemeberMeManager(
         		jdbcTemplate,applicationConfig,authTokenService,validity);
     }
-    
+
 }

+ 6 - 6
maxkey-authentications/maxkey-authentication-provider/src/main/java/org/dromara/maxkey/autoconfigure/JwtAuthnAutoConfiguration.java

@@ -42,14 +42,14 @@ public class JwtAuthnAutoConfiguration  {
      * @return
      */
     @Bean
-    public JWKSetKeyStore jwtLoginJwkSetKeyStore() {
+    JWKSetKeyStore jwtLoginJwkSetKeyStore() {
         JWKSetKeyStore jwkSetKeyStore = new JWKSetKeyStore();
         ClassPathResource classPathResource = new ClassPathResource("/config/loginjwkkeystore.jwks");
         jwkSetKeyStore.setLocation(classPathResource);
         _logger.debug("JWT Login JwkSet KeyStore init.");
         return jwkSetKeyStore;
     }
-    
+
     /**
      * jwt Login ValidationService.
      * @return
@@ -58,9 +58,9 @@ public class JwtAuthnAutoConfiguration  {
      * @throws NoSuchAlgorithmException 
      */
     @Bean
-    public DefaultJwtSigningAndValidationService jwtLoginValidationService(
-    		@Qualifier("jwtLoginJwkSetKeyStore") JWKSetKeyStore jwtLoginJwkSetKeyStore) 
-                    throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
+    DefaultJwtSigningAndValidationService jwtLoginValidationService(
+            @Qualifier("jwtLoginJwkSetKeyStore") JWKSetKeyStore jwtLoginJwkSetKeyStore)
+            throws NoSuchAlgorithmException, InvalidKeySpecException, JOSEException {
         DefaultJwtSigningAndValidationService jwtSignerValidationService = 
                 new DefaultJwtSigningAndValidationService(jwtLoginJwkSetKeyStore);
         jwtSignerValidationService.setDefaultSignerKeyId("maxkey_rsa");
@@ -74,7 +74,7 @@ public class JwtAuthnAutoConfiguration  {
      * @return
      */
     @Bean
-    public JwtLoginService jwtLoginService(
+    JwtLoginService jwtLoginService(
             @Value("${maxkey.login.jwt.issuer}")
             String issuer,
             @Qualifier("jwtLoginValidationService")

+ 2 - 0
maxkey-authentications/maxkey-authentication-provider/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -0,0 +1,2 @@
+org.dromara.maxkey.autoconfigure.AuthnProviderAutoConfiguration
+org.dromara.maxkey.autoconfigure.JwtAuthnAutoConfiguration

+ 1 - 1
maxkey-authentications/maxkey-authentication-social/src/main/java/me/zhyd/oauth/request/AuthWeChatEnterpriseWebRequestCost.java

@@ -40,7 +40,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class AuthWeChatEnterpriseWebRequestCost extends AbstractAuthWeChatEnterpriseRequest {
-    final static Logger _logger = LoggerFactory.getLogger(AuthWeChatEnterpriseWebRequestCost.class);
+    static final  Logger _logger = LoggerFactory.getLogger(AuthWeChatEnterpriseWebRequestCost.class);
     public AuthWeChatEnterpriseWebRequestCost(AuthConfig config) {
         super(config, AuthDefaultSource.WECHAT_ENTERPRISE_WEB);
     }

+ 1 - 1
maxkey-authentications/maxkey-authentication-social/src/main/java/org/dromara/maxkey/authn/support/socialsignon/AbstractSocialSignOnEndpoint.java

@@ -42,7 +42,7 @@ import me.zhyd.oauth.request.AuthRequest;
  *
  */
 public class AbstractSocialSignOnEndpoint {
-	final static Logger _logger = LoggerFactory.getLogger(AbstractSocialSignOnEndpoint.class);
+	static final  Logger _logger = LoggerFactory.getLogger(AbstractSocialSignOnEndpoint.class);
 	
 	protected AuthRequest authRequest;
 	

+ 26 - 26
maxkey-authentications/maxkey-authentication-social/src/main/java/org/dromara/maxkey/authn/support/socialsignon/SocialSignOnEndpoint.java

@@ -29,7 +29,7 @@ import org.dromara.maxkey.constants.ConstsLoginType;
 import org.dromara.maxkey.entity.Message;
 import org.dromara.maxkey.entity.SocialsAssociate;
 import org.dromara.maxkey.entity.SocialsProvider;
-import org.dromara.maxkey.entity.UserInfo;
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.dromara.maxkey.uuid.UUID;
 import org.dromara.maxkey.web.WebContext;
 import org.slf4j.Logger;
@@ -51,12 +51,12 @@ import java.util.Map;
 @Controller
 @RequestMapping(value = "/logon/oauth20")
 public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
-	final static Logger _logger = LoggerFactory.getLogger(SocialSignOnEndpoint.class);
+	static final  Logger _logger = LoggerFactory.getLogger(SocialSignOnEndpoint.class);
 
 	@RequestMapping(value={"/authorize/{provider}"}, method = RequestMethod.GET)
 	@ResponseBody
-	public ResponseEntity<?> authorize( HttpServletRequest request,
-										@PathVariable String provider
+	public Message<Object> authorize( HttpServletRequest request,
+										@PathVariable("provider") String provider
 									) {
 		_logger.trace("SocialSignOn provider : " + provider);
 		String instId = WebContext.getInst().getId();
@@ -69,12 +69,12 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 				).authorize(authTokenService.genRandomJwt());
 
 		_logger.trace("authorize SocialSignOn : " + authorizationUrl);
-		return new Message<Object>((Object)authorizationUrl).buildResponse();
+		return new Message<Object>((Object)authorizationUrl);
 	}
 
 	@RequestMapping(value={"/scanqrcode/{provider}"}, method = RequestMethod.GET)
 	@ResponseBody
-	public ResponseEntity<?> scanQRCode(HttpServletRequest request,
+	public Message<SocialsProvider> scanQRCode(HttpServletRequest request,
 										@PathVariable("provider") String provider) {
 		String instId = WebContext.getInst().getId();
 		String originURL =WebContext.getContextPath(request,false);
@@ -102,12 +102,12 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 			socialSignOnProviderService.setToken(state);
 		}
 		
-		return new Message<SocialsProvider>(scanQrProvider).buildResponse();
+		return new Message<SocialsProvider>(scanQrProvider);
 	}
 
 	
 	@RequestMapping(value={"/bind/{provider}"}, method = RequestMethod.GET)
-	public ResponseEntity<?> bind(@PathVariable String provider,
+	public Message<AuthJwt> bind(@PathVariable("provider") String provider,
 								  @CurrentUser UserInfo userInfo,
 								  HttpServletRequest request) {
 		 //auth call back may exception 
@@ -124,18 +124,18 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 			_logger.debug("Social Bind : "+socialsAssociate);
 			this.socialsAssociateService.delete(socialsAssociate);
 			this.socialsAssociateService.insert(socialsAssociate);
-			return new Message<AuthJwt>().buildResponse();
+			return new Message<AuthJwt>();
 	    }catch(Exception e) {
 	        _logger.error("callback Exception  ",e);
 	    }
 	    
-	    return new Message<AuthJwt>(Message.ERROR).buildResponse();
+	    return new Message<AuthJwt>(Message.ERROR);
 	}
 
 
 
 	@RequestMapping(value={"/callback/{provider}"}, method = RequestMethod.GET)
-	public ResponseEntity<?> callback(@PathVariable String provider,
+	public Message<AuthJwt> callback(@PathVariable("provider") String provider,
 									  HttpServletRequest request) {
 		 //auth call back may exception 
 	    try {
@@ -152,7 +152,7 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 				//如果存在第三方ID并且在数据库无法找到映射关系,则进行绑定逻辑
 				if (StringUtils.isNotEmpty(socialsAssociate.getSocialUserId())) {
 					//返回message为第三方用户标识
-					return new Message<AuthJwt>(Message.PROMPT,socialsAssociate.getSocialUserId()).buildResponse();
+					return new Message<AuthJwt>(Message.PROMPT,socialsAssociate.getSocialUserId());
 				}
 			}
 
@@ -171,10 +171,10 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 	    	//socialsAssociate.setExAttribute(JsonUtils.object2Json(accessToken.getResponseObject()));
 		
 	    	this.socialsAssociateService.update(socialsAssociate);
-	    	return new Message<AuthJwt>(authTokenService.genAuthJwt(authentication)).buildResponse();
+	    	return new Message<AuthJwt>(authTokenService.genAuthJwt(authentication));
 	    }catch(Exception e) {
 	    	 _logger.error("callback Exception  ",e);
-	    	 return new Message<AuthJwt>(Message.ERROR).buildResponse();
+	    	 return new Message<AuthJwt>(Message.ERROR);
 	    }
 	}
 
@@ -184,13 +184,13 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 	 * @return
 	 */
 	@RequestMapping(value={"/workweixin/qr/auth/login"}, method = {RequestMethod.POST})
-	public ResponseEntity<?> qrAuthLogin(
+	public Message<AuthJwt> qrAuthLogin(
 			@RequestParam Map<String, String> param,
 			HttpServletRequest request) {
 
 		try {
 			if (null == param){
-				return new Message<AuthJwt>(Message.ERROR).buildResponse();
+				return new Message<AuthJwt>(Message.ERROR);
 			}
 			String token = param.get("token");
 			String username = param.get("username");
@@ -200,15 +200,15 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 				//设置token和用户绑定
 				boolean flag = this.socialSignOnProviderService.bindtoken(token,username);
 				if (flag) {
-					return new Message<AuthJwt>().buildResponse();
+					return new Message<AuthJwt>();
 				}
 			} else {
-				return new Message<AuthJwt>(Message.WARNING,"Invalid token").buildResponse();
+				return new Message<AuthJwt>(Message.WARNING,"Invalid token");
 			}
 		}catch(Exception e) {
 			_logger.error("qrAuthLogin Exception  ",e);
 		}
-		return new Message<AuthJwt>(Message.ERROR).buildResponse();
+		return new Message<AuthJwt>(Message.ERROR);
 	}
 
 
@@ -220,22 +220,22 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 	 * @return
 	 */
 	@RequestMapping(value={"/qrcallback/{provider}/{state}"}, method = RequestMethod.GET)
-	public ResponseEntity<?> qrcallback(@PathVariable String provider,@PathVariable String state,
+	public Message<AuthJwt> qrcallback(@PathVariable("provider") String provider,@PathVariable("state") String state,
 										HttpServletRequest request) {
 		try {
 			//判断只有maxkey扫码
 			if (!provider.equalsIgnoreCase(AuthMaxkeyRequest.KEY)) {
-				return new Message<AuthJwt>(Message.ERROR).buildResponse();
+				return new Message<AuthJwt>(Message.ERROR);
 			}
 
 			String loginName = socialSignOnProviderService.getToken(state);
 			if (StringUtils.isEmpty(loginName)) {
 				//二维码过期
-				return new Message<AuthJwt>(Message.PROMPT).buildResponse();
+				return new Message<AuthJwt>(Message.PROMPT);
 			}
 			if("-1".equalsIgnoreCase(loginName)){
 				//暂无用户扫码
-				return new Message<AuthJwt>(Message.WARNING).buildResponse();
+				return new Message<AuthJwt>(Message.WARNING);
 			}
 			String instId = WebContext.getInst().getId();
 
@@ -250,7 +250,7 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 			_logger.debug("qrcallback Loaded SocialSignOn Socials Associate : "+socialsAssociate);
 
 			if(null == socialsAssociate) {
-				return new Message<AuthJwt>(Message.ERROR).buildResponse();
+				return new Message<AuthJwt>(Message.ERROR);
 			}
 
 			_logger.debug("qrcallback Social Sign On from {} mapping to user {}", socialsAssociate.getProvider(),socialsAssociate.getUsername());
@@ -266,10 +266,10 @@ public class SocialSignOnEndpoint  extends AbstractSocialSignOnEndpoint{
 			//socialsAssociate.setExAttribute(JsonUtils.object2Json(accessToken.getResponseObject()));
 
 			this.socialsAssociateService.update(socialsAssociate);
-			return new Message<AuthJwt>(authTokenService.genAuthJwt(authentication)).buildResponse();
+			return new Message<AuthJwt>(authTokenService.genAuthJwt(authentication));
 		}catch(Exception e) {
 			_logger.error("qrcallback Exception  ",e);
-			return new Message<AuthJwt>(Message.ERROR).buildResponse();
+			return new Message<AuthJwt>(Message.ERROR);
 		}
 	}
 }

+ 1 - 0
maxkey-authentications/maxkey-authentication-social/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -0,0 +1 @@
+org.dromara.maxkey.autoconfigure.SocialSignOnAutoConfiguration

+ 3 - 2
maxkey-common/build.gradle

@@ -3,5 +3,6 @@ description = "maxkey-common"
 dependencies {
 	//local jars
 	implementation fileTree(dir: '../maxkey-lib/', include: '*/*.jar')
-	
-}
+
+
+}

+ 40 - 0
maxkey-common/src/main/java/org/dromara/maxkey/adapter/LocalDateTimeAdapter.java

@@ -0,0 +1,40 @@
+/*
+ * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.dromara.maxkey.adapter;
+
+import com.google.gson.TypeAdapter;
+import com.google.gson.stream.JsonReader;
+import com.google.gson.stream.JsonWriter;
+
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+public class LocalDateTimeAdapter extends TypeAdapter<LocalDateTime> {
+    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+    @Override
+    public void write(JsonWriter out, LocalDateTime value) throws IOException {
+        out.value(value.format(formatter));
+    }
+
+    @Override
+    public LocalDateTime read(JsonReader in) throws IOException {
+        return LocalDateTime.parse(in.nextString(), formatter);
+    }
+}

+ 2 - 1
maxkey-common/src/main/java/org/dromara/maxkey/crypto/ReciprocalUtils.java

@@ -28,10 +28,11 @@ import javax.crypto.Cipher;
 import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
 
+import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.logging.LogFactory;
 import org.dromara.maxkey.util.Instance;
 import org.dromara.maxkey.util.StringGenerator;
-import org.dromara.maxkey.util.StringUtils;
+import org.dromara.maxkey.util.StrUtils;
 
 /**
  * Reciprocal cipher or Symmetric-key algorithm

+ 1 - 1
maxkey-common/src/main/java/org/dromara/maxkey/crypto/jwt/HMAC512Service.java

@@ -33,7 +33,7 @@ import com.nimbusds.jose.util.Base64URL;
 
 public class HMAC512Service {
 
-	public final static String MXK_AUTH_JWK = "mxk_auth_jwk";
+	public static final  String MXK_AUTH_JWK = "mxk_auth_jwk";
 	
 	JWSSigner signer;
 	

+ 1 - 1
maxkey-common/src/main/java/org/dromara/maxkey/crypto/jwt/encryption/service/impl/RecipientJwtEncryptionAndDecryptionServiceBuilder.java

@@ -37,7 +37,7 @@ import com.nimbusds.jose.jwk.JWKSet;
  *
  */
 public class RecipientJwtEncryptionAndDecryptionServiceBuilder {
-	final static Logger _logger = LoggerFactory.getLogger(RecipientJwtEncryptionAndDecryptionServiceBuilder.class);
+	static final  Logger _logger = LoggerFactory.getLogger(RecipientJwtEncryptionAndDecryptionServiceBuilder.class);
 	
 	//private HttpClient httpClient = HttpClientBuilder.create().useSystemProperties().build();
 	//private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);

+ 1 - 1
maxkey-common/src/main/java/org/dromara/maxkey/crypto/jwt/signer/service/impl/DefaultJwtSigningAndValidationService.java

@@ -46,7 +46,7 @@ import com.nimbusds.jose.jwk.RSAKey;
 import com.nimbusds.jwt.SignedJWT;
 
 public class DefaultJwtSigningAndValidationService implements JwtSigningAndValidationService {
-	final static Logger _logger = LoggerFactory.getLogger(DefaultJwtSigningAndValidationService.class);
+	static final  Logger _logger = LoggerFactory.getLogger(DefaultJwtSigningAndValidationService.class);
 	
 	// map of identifier to signer
 	private Map<String, JWSSigner> signers = new HashMap<String, JWSSigner>();

+ 1 - 1
maxkey-common/src/main/java/org/dromara/maxkey/crypto/jwt/signer/service/impl/SymmetricSigningAndValidationServiceBuilder.java

@@ -37,7 +37,7 @@ import com.nimbusds.jose.jwk.JWK;
  * Builder Symmetric Signing Service
  */
 public class SymmetricSigningAndValidationServiceBuilder {
-	final static Logger _logger = LoggerFactory.getLogger(SymmetricSigningAndValidationServiceBuilder.class);
+	static final  Logger _logger = LoggerFactory.getLogger(SymmetricSigningAndValidationServiceBuilder.class);
 	public static final String SYMMETRIC_KEY = "SYMMETRIC-KEY";
 	/**
 	 * 

+ 7 - 7
maxkey-common/src/main/java/org/dromara/maxkey/entity/Message.java

@@ -21,12 +21,12 @@ import org.springframework.http.ResponseEntity;
 
 public class Message<T> {
 	
-	public final static int SUCCESS	= 0;	//成功
-	public final static int ERROR	= 1;	//错误
-	public final static int FAIL	= 2;	//失败
-	public final static int INFO	= 101;	//信息
-	public final static int PROMPT	= 102;	//提示
-	public final static int WARNING	= 103;	//警告
+	public static final  int SUCCESS	= 0;	//成功
+	public static final  int ERROR		= 1;	//错误
+	public static final  int FAIL		= 2;	//失败
+	public static final  int INFO		= 101;	//信息
+	public static final  int PROMPT		= 102;	//提示
+	public static final  int WARNING	= 103;	//警告
 	
 	int code;
 	
@@ -89,7 +89,7 @@ public class Message<T> {
 	public void setData(T data) {
 		this.data = data;
 	}
-
+	
 	public ResponseEntity<?>  buildResponse() {
 		return ResponseEntity.ok(this);
 	}

+ 1 - 1
maxkey-common/src/main/java/org/dromara/maxkey/pretty/Pretty.java

@@ -18,7 +18,7 @@
 package org.dromara.maxkey.pretty;
 
 public interface Pretty {
-	public final static String LINE_BREAK 	= "\n";
+	public static final  String LINE_BREAK 	= "\n";
 	
 	public String format(String source);
 

+ 2 - 7
maxkey-common/src/main/java/org/dromara/maxkey/util/AuthorizationHeaderUtils.java

@@ -17,6 +17,7 @@
 
 package org.dromara.maxkey.util;
 
+import org.apache.commons.lang3.StringUtils;
 import org.dromara.maxkey.crypto.Base64Utils;
 
 import jakarta.servlet.http.HttpServletRequest;
@@ -88,13 +89,7 @@ public class AuthorizationHeaderUtils {
     }
     
     static boolean isBearer(String bearer) {
-        if (bearer.toLowerCase().startsWith(AuthorizationHeader.Credential.BEARER.toLowerCase())) {
-            return true;
-        } else {
-            return false;
-        }
+        return (bearer.toLowerCase().startsWith(AuthorizationHeader.Credential.BEARER.toLowerCase()));
     }
     
-   
-
 }

+ 32 - 32
maxkey-common/src/main/java/org/dromara/maxkey/util/DateUtils.java

@@ -30,33 +30,33 @@ import org.joda.time.chrono.ISOChronology;
 
 
 public class DateUtils {
-	public final static String FORMAT_DATE_DEFAULT = "yyyy-MM-dd";
+	public static final  String FORMAT_DATE_DEFAULT = "yyyy-MM-dd";
 
-	public final static String FORMAT_DATE_YYYYMMDD = "yyyyMMdd";
+	public static final  String FORMAT_DATE_YYYYMMDD = "yyyyMMdd";
 
-	public final static String FORMAT_DATE_YYYY_MM_DD = "yyyy-MM-dd";
+	public static final  String FORMAT_DATE_YYYY_MM_DD = "yyyy-MM-dd";
 	
-	public final static String FORMAT_DATE_PATTERN_1="yyyy/MM/dd";
-	public final static String FORMAT_DATE_PATTERN_2="yyyy/M/dd";
-	public final static String FORMAT_DATE_PATTERN_3="yyyy/MM/d";
-	public final static String FORMAT_DATE_PATTERN_4="yyyy/M/d";
-	public final static String FORMAT_DATE_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+	public static final  String FORMAT_DATE_PATTERN_1="yyyy/MM/dd";
+	public static final  String FORMAT_DATE_PATTERN_2="yyyy/M/dd";
+	public static final  String FORMAT_DATE_PATTERN_3="yyyy/MM/d";
+	public static final  String FORMAT_DATE_PATTERN_4="yyyy/M/d";
+	public static final  String FORMAT_DATE_YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
 	
-	public final static String FORMAT_DATE_ISO_TIMESTAMP="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
+	public static final  String FORMAT_DATE_ISO_TIMESTAMP="yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
 
-	public final static String FORMAT_DATE_YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+	public static final  String FORMAT_DATE_YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
 
-	public final static String FORMAT_DATE_YYYY_MM_DD_HHMM = "yyyy-MM-dd HHmm";
+	public static final  String FORMAT_DATE_YYYY_MM_DD_HHMM = "yyyy-MM-dd HHmm";
 
-	public final static String FORMAT_DATE_YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
+	public static final  String FORMAT_DATE_YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
 
-	public final static String FORMAT_DATE_HH_MM = "HH:mm";
+	public static final  String FORMAT_DATE_HH_MM = "HH:mm";
 
-	public final static String FORMAT_DATE_HH_MM_SS = "HH:mm:ss";
+	public static final  String FORMAT_DATE_HH_MM_SS = "HH:mm:ss";
 
-	public final static String FORMAT_DATE_HHMM = "HHmm";
+	public static final  String FORMAT_DATE_HHMM = "HHmm";
 
-	public final static String FORMAT_DATE_HHMMSS = "HHmmss";
+	public static final  String FORMAT_DATE_HHMMSS = "HHmmss";
 
 	public static final String FORMAT_WORK_TIME = "yyyy-MM-dd HHmmss";
 	/**
@@ -74,7 +74,7 @@ public class DateUtils {
 	 *         stringValue2.
 	 * @since 1.2
 	 */
-	public final static int compareDate(String stringValue1, String stringValue2)
+	public static final  int compareDate(String stringValue1, String stringValue2)
 			throws ParseException {
 		Date date1 = tryParse(stringValue1);
 		if (date1 == null) {
@@ -95,11 +95,11 @@ public class DateUtils {
 	 * 
 	 * @see #FORMAT_DATE_DEFAULT
 	 */
-	public final static String getCurrentDateAsString() {
+	public static final  String getCurrentDateAsString() {
 		return getCurrentDateAsString(FORMAT_DATE_DEFAULT);
 	}
 	
-	public final static String getCurrentDateTimeAsString() {
+	public static final  String getCurrentDateTimeAsString() {
 		return getCurrentDateAsString(FORMAT_DATE_YYYY_MM_DD_HH_MM_SS);
 	}
 
@@ -112,12 +112,12 @@ public class DateUtils {
 	 * @return current system date.
 	 * 
 	 */
-	public final static String getCurrentDateAsString(String formatPattern) {
+	public static final  String getCurrentDateAsString(String formatPattern) {
 		Date date = new Date();
 		return format(date, formatPattern);
 	}
 	
-	public final static String getFormtPattern1ToPattern2(String stringValue,String formatPattern1,String formatPattern2){
+	public static final  String getFormtPattern1ToPattern2(String stringValue,String formatPattern1,String formatPattern2){
 		Date date = parse(stringValue, formatPattern1);
 		return format(date, formatPattern2);
 	}
@@ -127,7 +127,7 @@ public class DateUtils {
 	 * 
 	 * @return current system date.
 	 */
-	public final static Date getCurrentDate() {
+	public static final  Date getCurrentDate() {
 		return new Date();
 	}
 
@@ -135,7 +135,7 @@ public class DateUtils {
 	 * 0������, 1����һ, 2���ڶ�, 3������, 4������, 5������,6������
 	 * @return
 	 */
-	public final static String getTodayOfWeek(){
+	public static final  String getTodayOfWeek(){
 		Calendar calendar = Calendar.getInstance();   
 		Date date = new Date();   
 		calendar.setTime(date);   
@@ -149,7 +149,7 @@ public class DateUtils {
 	 * @param endTime
 	 * @return
 	 */
-	public final static boolean compareTime(String startTime,String endTime) throws ParseException{
+	public static final  boolean compareTime(String startTime,String endTime) throws ParseException{
 		SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");
 			Date start = sdf.parse(startTime);
 			Date end = sdf.parse(endTime);
@@ -180,7 +180,7 @@ public class DateUtils {
 	 * 
 	 * @see #FORMAT_DATE_DEFAULT
 	 */
-	public final static String format(Date date) {
+	public static final  String format(Date date) {
 		if (date == null) {
 			return "";
 		}
@@ -196,7 +196,7 @@ public class DateUtils {
 	 * 
 	 * @see #FORMAT_DATE_DEFAULT
 	 */
-	public final static String formatDateTime(Date date) {
+	public static final  String formatDateTime(Date date) {
 		if (date == null) {
 			return "";
 		}
@@ -212,7 +212,7 @@ public class DateUtils {
 	 * 
 	 * @see #FORMAT_DATE_DEFAULT
 	 */
-	public final static String formatTimestamp(Date date) {
+	public static final  String formatTimestamp(Date date) {
 		if (date == null) {
 			return "";
 		}
@@ -228,7 +228,7 @@ public class DateUtils {
 	 * 
 	 * @see #FORMAT_DATE_DEFAULT
 	 */
-	public final static Date parseTimestamp(String date) {
+	public static final  Date parseTimestamp(String date) {
 		if (date == null) {
 			return null;
 		}
@@ -250,7 +250,7 @@ public class DateUtils {
 	 * @see #FORMAT_DATE_YYYY_MM_DD_HH_MM_SS
 	 * @see #FORMAT_DATE_YYYY_MM_DD_HHMMSS
 	 */
-	public final static String format(Date date, String formatPattern) {
+	public static final  String format(Date date, String formatPattern) {
 		if (date == null) {
 			return "";
 		}
@@ -265,7 +265,7 @@ public class DateUtils {
 	 * @return Date represents stringValue.
 	 * @see #FORMAT_DATE_DEFAULT
 	 */
-	public final static Date parse(String stringValue) {
+	public static final  Date parse(String stringValue) {
 		return parse(stringValue, FORMAT_DATE_DEFAULT);
 	}
 
@@ -279,7 +279,7 @@ public class DateUtils {
 	 * @return Date represents stringValue, null while parse exception occurred.
 	 * @see #FORMAT_DATE_DEFAULT
 	 */
-	public final static Date parse(String stringValue, String formatPattern) {
+	public static final  Date parse(String stringValue, String formatPattern) {
 		SimpleDateFormat format = new SimpleDateFormat(formatPattern);
 		try {
 			return format.parse(stringValue);
@@ -297,7 +297,7 @@ public class DateUtils {
 	 *            string value.
 	 * @return Date represents stringValue, null while parse exception occurred.
 	 */
-	public final static Date tryParse(String stringValue) {
+	public static final  Date tryParse(String stringValue) {
 		Date date = parse(stringValue, FORMAT_DATE_YYYY_MM_DD);
 		if (date != null) {
 			return date;

+ 1 - 1
maxkey-common/src/main/java/org/dromara/maxkey/util/EthernetAddress.java

@@ -35,7 +35,7 @@ public class EthernetAddress
     
     private static final long serialVersionUID = 1L;
 
-    private final static char[] HEX_CHARS = "0123456789abcdefABCDEF".toCharArray();
+    private static final  char[] HEX_CHARS = "0123456789abcdefABCDEF".toCharArray();
 
     /**
      * We may need a random number generator, for creating dummy ethernet

+ 1 - 0
maxkey-common/src/main/java/org/dromara/maxkey/util/PathUtils.java

@@ -19,6 +19,7 @@ package org.dromara.maxkey.util;
 
 import java.nio.file.Paths;
 
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 

+ 42 - 42
maxkey-common/src/main/java/org/dromara/maxkey/util/RQCodeUtils.java → maxkey-common/src/main/java/org/dromara/maxkey/util/QRCodeUtils.java

@@ -1,19 +1,19 @@
 /*
  * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  *     http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- 
+
 
 package org.dromara.maxkey.util;
 
@@ -25,60 +25,60 @@ import com.google.zxing.BarcodeFormat;
 import com.google.zxing.MultiFormatWriter;
 import com.google.zxing.common.BitMatrix;
 
-public class RQCodeUtils {
+public class QRCodeUtils {
+
 
-	
 	public static void write2File(String path,String rqCodeText,String format,int width, int height ){
-		try {  
+		try {
 			BitMatrix byteMatrix=genRQCode(rqCodeText,width,height);
-			
-	        File file = new File(path);  
-	          
-	        QRCode.writeToPath(byteMatrix, format, file); 
-		} catch (Exception e) {  
-            e.printStackTrace();  
-        }  
+
+	        File file = new File(path);
+
+	        QRCode.writeToPath(byteMatrix, format, file);
+		} catch (Exception e) {
+            e.printStackTrace();
+        }
 	}
-	
-	public static BufferedImage write2BufferedImage(String rqCodeText,String format,int width, int height ){
-		try {  
-			BitMatrix byteMatrix=genRQCode(rqCodeText,width,height); 
-	          
-	        return QRCode.toBufferedImage(byteMatrix); 
-		} catch (Exception e) {  
-            e.printStackTrace();  
-        }  
+
+	public static BufferedImage write2BufferedImage(String rqCodeText,String format,int width, int height){
+		try {
+			BitMatrix byteMatrix=genRQCode(rqCodeText,width,height);
+
+	        return QRCode.toBufferedImage(byteMatrix);
+		} catch (Exception e) {
+            e.printStackTrace();
+        }
 		return null;
 	}
-	
+
 	public static void write2OutputStream(OutputStream stream,String rqCodeText,String format,int width, int height ){
-		try {  
+		try {
 			BitMatrix byteMatrix=genRQCode(rqCodeText,width,height);
-	          
-	        QRCode.writeToStream(byteMatrix, format, stream); 
-		} catch (Exception e) {  
-            e.printStackTrace();  
-        }  
+
+	        QRCode.writeToStream(byteMatrix, format, stream);
+		} catch (Exception e) {
+            e.printStackTrace();
+        }
 	}
-	
-	
-	public static BitMatrix genRQCode(String rqCodeText,int width, int height ){
+
+
+	public static BitMatrix genRQCode(String rqCodeText,int width, int height){
 		if(width==0){
 			width=200;
 		}
 		if(height==0){
 			height=200;
 		}
-		try {  
+		try {
 			return  new MultiFormatWriter().encode(
-	        		rqCodeText, 
-	        		BarcodeFormat.QR_CODE, 
-	        		width, 
-	        		height);  
-		} catch (Exception e) {  
-            e.printStackTrace();  
-        }  
+	        		rqCodeText,
+	        		BarcodeFormat.QR_CODE,
+	        		width,
+	        		height);
+		} catch (Exception e) {
+            e.printStackTrace();
+        }
 		return null;
 	}
-	
+
 }

+ 10 - 10
maxkey-common/src/main/java/org/dromara/maxkey/util/SnowFlakeId.java

@@ -31,28 +31,28 @@ public class SnowFlakeId {
     /**
      * 起始的时间戳
      */
-    private final static long START_STMP = 1480166465631L;
+    private static final  long START_STMP = 1480166465631L;
 
     /**
      * 每一部分占用的位数
      */
-    private final static long SEQUENCE_BIT = 12; //序列号占用的位数
-    private final static long MACHINE_BIT = 5;   //机器标识占用的位数
-    private final static long DATACENTER_BIT = 5;//数据中心占用的位数
+    private static final  long SEQUENCE_BIT = 12; //序列号占用的位数
+    private static final  long MACHINE_BIT = 5;   //机器标识占用的位数
+    private static final  long DATACENTER_BIT = 5;//数据中心占用的位数
 
     /**
      * 每一部分的最大值
      */
-    private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
-    private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
-    private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
+    private static final  long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
+    private static final  long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
+    private static final  long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
 
     /**
      * 每一部分向左的位移
      */
-    private final static long MACHINE_LEFT = SEQUENCE_BIT;
-    private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
-    private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;
+    private static final  long MACHINE_LEFT = SEQUENCE_BIT;
+    private static final  long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
+    private static final  long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;
 
     private long datacenterId;  //数据中心
     private long machineId;     //机器标识

+ 6 - 4
maxkey-common/src/main/java/org/dromara/maxkey/util/StringUtils.java → maxkey-common/src/main/java/org/dromara/maxkey/util/StrUtils.java

@@ -27,7 +27,9 @@ import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-public final class StringUtils extends org.apache.commons.lang3.StringUtils {
+import org.apache.commons.lang3.StringUtils;
+
+public final class StrUtils {
 
     /*
      * 获取指定UTF-8模式字节长度的字符串
@@ -165,7 +167,7 @@ public final class StringUtils extends org.apache.commons.lang3.StringUtils {
      * @return
      */
     public static Boolean containsPartOrAll(String string, String string2) {
-        if (isNotEmpty(string) && isNotEmpty(string2)) {
+        if (StringUtils.isNotEmpty(string) && StringUtils.isNotEmpty(string2)) {
             return Pattern.compile("[" + string + "]").matcher(string2).find();
         }
         return false;
@@ -287,7 +289,7 @@ public final class StringUtils extends org.apache.commons.lang3.StringUtils {
         List<String> idList = new ArrayList<String>();
         List<String> nameList = new ArrayList<String>();
         if (StringUtils.isNotEmpty(proValue)) {
-            List<String> list = StringUtils.string2List(proValue, ",");
+            List<String> list = StrUtils.string2List(proValue, ",");
             for (String str : list) {
                 idList.add(str.split("\\,")[0]);
                 nameList.add(str.split("\\,")[1]);
@@ -410,7 +412,7 @@ public final class StringUtils extends org.apache.commons.lang3.StringUtils {
      * }else{ pinyin += nameChar[i]; } } return pinyin; }
      */
     public static Map<String, String> aduserName2Map(String activeDirectoryUserName) {
-        if (isEmpty(activeDirectoryUserName)) {
+        if (StringUtils.isEmpty(activeDirectoryUserName)) {
             return null;
         }
         Map<String, String> map = new HashMap<String, String>();

+ 54 - 0
maxkey-common/src/main/java/org/dromara/maxkey/util/TimeJsonUtils.java

@@ -0,0 +1,54 @@
+/*
+ * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.dromara.maxkey.util;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import org.dromara.maxkey.adapter.LocalDateTimeAdapter;
+
+import java.time.LocalDateTime;
+
+/**
+ * @description:
+ * @author: orangeBabu
+ * @time: 16/8/2024 PM6:23
+ */
+public class TimeJsonUtils {
+    public static <T> T gsonStringToObject(String json, Class<T> cls) {
+        Gson gson = new GsonBuilder()
+                .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter())
+                .create();
+        return gson.fromJson(json, cls);
+    }
+
+    /**
+     * Gson Transform java bean object to json string .
+     *
+     * @param bean Object
+     * @return string
+     */
+    public static String gsonToString(Object bean) {
+        String json = "";
+        Gson gson = new GsonBuilder()
+                .registerTypeAdapter(LocalDateTime.class, new LocalDateTimeAdapter())
+                .create();
+        json = gson.toJson(bean);
+
+        return json;
+    }
+}

+ 0 - 1
maxkey-core/src/main/java/org/dromara/maxkey/configuration/ApplicationConfig.java

@@ -17,7 +17,6 @@
 
 package org.dromara.maxkey.configuration;
 
-import org.apache.commons.lang3.StringUtils;
 import org.dromara.maxkey.constants.ConstsDatabase;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;

+ 5 - 5
maxkey-core/src/main/java/org/dromara/maxkey/entity/GroupPermissions.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/Access.java

@@ -28,8 +28,8 @@ import jakarta.persistence.Table;
 import org.dromara.maxkey.entity.apps.Apps;
 
 @Entity
-@Table(name = "mxk_group_permissions")  
-public class GroupPermissions extends Apps implements Serializable{
+@Table(name = "mxk_access")  
+public class Access extends Apps implements Serializable{
 
 	/**
 	 * 
@@ -54,7 +54,7 @@ public class GroupPermissions extends Apps implements Serializable{
 
 	private String instName;
 	
-	public GroupPermissions(){
+	public Access(){
 		super();
 	}
 	
@@ -63,7 +63,7 @@ public class GroupPermissions extends Apps implements Serializable{
 	 * @param groupId
 	 * @param appId
 	 */
-	public GroupPermissions(String groupId, String appId, String instId) {
+	public Access(String groupId, String appId, String instId) {
 		super();
 		this.groupId = groupId;
 		this.appId = appId;
@@ -150,7 +150,7 @@ public class GroupPermissions extends Apps implements Serializable{
 	@Override
 	public String toString() {
 		StringBuilder builder = new StringBuilder();
-		builder.append("GroupPermissions [id=");
+		builder.append("Access [id=");
 		builder.append(id);
 		builder.append(", groupId=");
 		builder.append(groupId);

+ 1 - 0
maxkey-core/src/main/java/org/dromara/maxkey/entity/Accounts.java

@@ -21,6 +21,7 @@ import java.io.Serializable;
 import java.util.HashMap;
 import java.util.List;
 
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.dromara.mybatis.jpa.entity.JpaEntity;
 import org.hibernate.validator.constraints.Length;
 

+ 1 - 0
maxkey-core/src/main/java/org/dromara/maxkey/entity/ChangePassword.java

@@ -19,6 +19,7 @@ package org.dromara.maxkey.entity;
 
 import java.util.Date;
 
+import org.dromara.maxkey.entity.idm.UserInfo;
 import org.dromara.mybatis.jpa.entity.JpaEntity;
 
 public class ChangePassword extends JpaEntity{

+ 1 - 2
maxkey-core/src/main/java/org/dromara/maxkey/entity/FileUpload.java

@@ -34,8 +34,7 @@ import jakarta.persistence.Table;
 @Entity
 @Table(name = "MXK_FILE_UPLOAD")
 public class FileUpload extends JpaEntity {
-	private static final long serialVersionUID = -4338400992411166457L;
-
+	
 	@Id
     @Column
     @GeneratedValue

+ 0 - 14
maxkey-core/src/main/java/org/dromara/maxkey/entity/Institutions.java

@@ -78,9 +78,6 @@ public class Institutions extends JpaEntity implements Serializable {
 	private String consoleTitle;
 	
 	@Column
-	private String captcha;
-	
-	@Column
 	private String defaultUri;
 
 
@@ -249,15 +246,6 @@ public class Institutions extends JpaEntity implements Serializable {
 		this.description = description;
 	}
 
-
-	public String getCaptcha() {
-		return captcha;
-	}
-
-	public void setCaptcha(String captcha) {
-		this.captcha = captcha;
-	}
-
 	public String getDefaultUri() {
 		return defaultUri;
 	}
@@ -309,8 +297,6 @@ public class Institutions extends JpaEntity implements Serializable {
 		builder.append(consoleDomain);
 		builder.append(", consoleTitle=");
 		builder.append(consoleTitle);
-		builder.append(", captcha=");
-		builder.append(captcha);
 		builder.append(", defaultUri=");
 		builder.append(defaultUri);
 		builder.append("]");

+ 0 - 142
maxkey-core/src/main/java/org/dromara/maxkey/entity/Localization.java

@@ -1,142 +0,0 @@
-/*
- * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- 
-
-package org.dromara.maxkey.entity;
-
-import java.io.Serializable;
-
-import org.dromara.mybatis.jpa.entity.JpaEntity;
-
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-
-@Entity
-@Table(name = "MXK_LOCALIZATION")
-public class Localization  extends JpaEntity implements Serializable {
-
-	/**
-	 * 
-	 */
-	private static final long serialVersionUID = -142504964446659847L;
-	@Id
-	@Column
-	@GeneratedValue
-	private String id;
-	
-	@Column
-	private String property;
-
-	@Column
-	private String langZh;
-	
-	@Column
-	private String langEn;
-	
-	@Column
-	private String description;
-	
-	@Column
-	private int status;
-	
-	@Column
-	private String instId;
-
-	public String getId() {
-		return id;
-	}
-
-	public void setId(String id) {
-		this.id = id;
-	}
-
-
-
-	public String getProperty() {
-		return property;
-	}
-
-	public void setProperty(String property) {
-		this.property = property;
-	}
-
-
-
-	public String getLangZh() {
-		return langZh;
-	}
-
-	public void setLangZh(String langZh) {
-		this.langZh = langZh;
-	}
-
-	public String getLangEn() {
-		return langEn;
-	}
-
-	public void setLangEn(String langEn) {
-		this.langEn = langEn;
-	}
-
-	public String getDescription() {
-		return description;
-	}
-
-	public void setDescription(String description) {
-		this.description = description;
-	}
-
-	public int getStatus() {
-		return status;
-	}
-
-	public void setStatus(int status) {
-		this.status = status;
-	}
-
-	public String getInstId() {
-		return instId;
-	}
-
-	public void setInstId(String instId) {
-		this.instId = instId;
-	}
-
-	@Override
-	public String toString() {
-		StringBuilder builder = new StringBuilder();
-		builder.append("Localization [id=");
-		builder.append(id);
-		builder.append(", property=");
-		builder.append(property);
-		builder.append(", langZh=");
-		builder.append(langZh);
-		builder.append(", langEn=");
-		builder.append(langEn);
-		builder.append(", description=");
-		builder.append(description);
-		builder.append(", status=");
-		builder.append(status);
-		builder.append(", instId=");
-		builder.append(instId);
-		builder.append("]");
-		return builder.toString();
-	}
-
-}

+ 0 - 6
maxkey-core/src/main/java/org/dromara/maxkey/entity/Saml20Metadata.java

@@ -20,12 +20,6 @@ package org.dromara.maxkey.entity;
 import java.io.Serializable;
 import org.dromara.mybatis.jpa.entity.JpaEntity;
 
-import jakarta.persistence.Column;
-import jakarta.persistence.Entity;
-import jakarta.persistence.GeneratedValue;
-import jakarta.persistence.Id;
-import jakarta.persistence.Table;
-
 /**
  * Saml20Metadata.
  * @author Crystal.Sea

+ 4 - 4
maxkey-core/src/main/java/org/dromara/maxkey/entity/EmailSenders.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/cnf/CnfEmailSenders.java

@@ -15,7 +15,7 @@
  */
  
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.cnf;
 
 
 
@@ -31,8 +31,8 @@ import jakarta.persistence.Id;
 import jakarta.persistence.Table;
 
 @Entity
-@Table(name = "MXK_EMAIL_SENDERS")
-public class EmailSenders  extends JpaEntity  implements Serializable {
+@Table(name = "MXK_CNF_EMAIL_SENDERS")
+public class CnfEmailSenders  extends JpaEntity  implements Serializable {
 
 	/**
 	 * 
@@ -91,7 +91,7 @@ public class EmailSenders  extends JpaEntity  implements Serializable {
     @Column
     private Date modifiedDate;
 
-	public EmailSenders() {
+	public CnfEmailSenders() {
 		super();
 	}
 

+ 4 - 4
maxkey-core/src/main/java/org/dromara/maxkey/entity/LdapContext.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/cnf/CnfLdapContext.java

@@ -15,7 +15,7 @@
  */
  
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.cnf;
 
 import java.io.Serializable;
 import java.util.Date;
@@ -29,8 +29,8 @@ import jakarta.persistence.Id;
 import jakarta.persistence.Table;
 
 @Entity
-@Table(name = "MXK_LDAP_CONTEXT")
-public class LdapContext extends JpaEntity implements Serializable {
+@Table(name = "MXK_CNF_LDAP_CONTEXT")
+public class CnfLdapContext extends JpaEntity implements Serializable {
 
 
 	/**
@@ -81,7 +81,7 @@ public class LdapContext extends JpaEntity implements Serializable {
 
 	private String instName;
 
-    public LdapContext() {
+    public CnfLdapContext() {
     }
 
 	public String getId() {

+ 3 - 3
maxkey-core/src/main/java/org/dromara/maxkey/entity/PasswordPolicy.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/cnf/CnfPasswordPolicy.java

@@ -15,7 +15,7 @@
  */
 
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.cnf;
 
 import org.dromara.mybatis.jpa.entity.JpaEntity;
 
@@ -39,8 +39,8 @@ import java.util.List;
  */
 
 @Entity
-@Table(name = "MXK_PASSWORD_POLICY")
-public class PasswordPolicy extends JpaEntity implements java.io.Serializable {
+@Table(name = "MXK_CNF_PASSWORD_POLICY")
+public class CnfPasswordPolicy extends JpaEntity implements java.io.Serializable {
 
     private static final long serialVersionUID = -4797776994287829182L;
     @Id

+ 4 - 4
maxkey-core/src/main/java/org/dromara/maxkey/entity/SmsProvider.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/cnf/CnfSmsProvider.java

@@ -15,7 +15,7 @@
  */
  
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.cnf;
 
 import java.io.Serializable;
 import java.util.Date;
@@ -29,8 +29,8 @@ import jakarta.persistence.Id;
 import jakarta.persistence.Table;
 
 @Entity
-@Table(name = "MXK_SMS_PROVIDER")
-public class SmsProvider extends JpaEntity implements Serializable {
+@Table(name = "MXK_CNF_SMS_PROVIDER")
+public class CnfSmsProvider extends JpaEntity implements Serializable {
 
 
 	/**
@@ -75,7 +75,7 @@ public class SmsProvider extends JpaEntity implements Serializable {
 
 	private String instName;
 
-    public SmsProvider() {
+    public CnfSmsProvider() {
     }
 
 	public String getId() {

+ 6 - 2
maxkey-webs/maxkey-web-maxkey/src/main/java/org/dromara/maxkey/web/access/contorller/package-info.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/dto/TimeBasedDto.java

@@ -1,5 +1,5 @@
 /*
- * Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
+ * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,4 +15,8 @@
  */
  
 
-package org.dromara.maxkey.web.access.contorller;
+package org.dromara.maxkey.entity.dto;
+
+public record TimeBasedDto(String displayName,String username,int digits,int period,String sharedSecret,String qrCode,String otpCode) {
+
+}

+ 1 - 1
maxkey-core/src/main/java/org/dromara/maxkey/entity/HistoryConnector.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/history/HistoryConnector.java

@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.history;
 
 import java.io.Serializable;
 import java.util.Date;

+ 1 - 1
maxkey-core/src/main/java/org/dromara/maxkey/entity/HistoryLogin.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/history/HistoryLogin.java

@@ -15,7 +15,7 @@
  */
  
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.history;
 
 import java.io.Serializable;
 import java.util.Date;

+ 1 - 1
maxkey-core/src/main/java/org/dromara/maxkey/entity/HistoryLoginApps.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/history/HistoryLoginApps.java

@@ -15,7 +15,7 @@
  */
  
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.history;
 
 import java.io.Serializable;
 import java.util.Date;

+ 1 - 1
maxkey-core/src/main/java/org/dromara/maxkey/entity/HistorySynchronizer.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/history/HistorySynchronizer.java

@@ -15,7 +15,7 @@
  */
  
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.history;
 
 import java.io.Serializable;
 import java.util.Date;

+ 1 - 1
maxkey-core/src/main/java/org/dromara/maxkey/entity/HistorySystemLogs.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/history/HistorySystemLogs.java

@@ -15,7 +15,7 @@
  */
  
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.history;
 
 import java.io.Serializable;
 import java.util.Date;

+ 1 - 1
maxkey-core/src/main/java/org/dromara/maxkey/entity/GroupMember.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/idm/GroupMember.java

@@ -15,7 +15,7 @@
  */
  
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.idm;
 
 import java.io.Serializable;
 

+ 1 - 25
maxkey-core/src/main/java/org/dromara/maxkey/entity/Groups.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/idm/Groups.java

@@ -15,7 +15,7 @@
  */
  
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.idm;
 
 import java.io.Serializable;
 import java.util.Date;
@@ -65,10 +65,6 @@ public class Groups extends JpaEntity implements Serializable {
     
     @Column
     String orgIdsList;
-    @Column
-    String resumeTime; 
-    @Column
-    String suspendTime;
     
     @Column
     int isdefault;
@@ -228,22 +224,6 @@ public class Groups extends JpaEntity implements Serializable {
         this.orgIdsList = orgIdsList;
     }
 
-    public String getResumeTime() {
-        return resumeTime;
-    }
-
-    public void setResumeTime(String resumeTime) {
-        this.resumeTime = resumeTime;
-    }
-
-    public String getSuspendTime() {
-        return suspendTime;
-    }
-
-    public void setSuspendTime(String suspendTime) {
-        this.suspendTime = suspendTime;
-    }
-
     public String getInstId() {
 		return instId;
 	}
@@ -275,10 +255,6 @@ public class Groups extends JpaEntity implements Serializable {
 		builder.append(filters);
 		builder.append(", orgIdsList=");
 		builder.append(orgIdsList);
-		builder.append(", resumeTime=");
-		builder.append(resumeTime);
-		builder.append(", suspendTime=");
-		builder.append(suspendTime);
 		builder.append(", isdefault=");
 		builder.append(isdefault);
 		builder.append(", description=");

+ 1 - 1
maxkey-core/src/main/java/org/dromara/maxkey/entity/Organizations.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/idm/Organizations.java

@@ -15,7 +15,7 @@
  */
  
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.idm;
 
 import java.io.Serializable;
 import java.util.Date;

+ 12 - 7
maxkey-core/src/main/java/org/dromara/maxkey/entity/UserInfo.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/idm/UserInfo.java

@@ -15,7 +15,7 @@
  */
  
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.idm;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 
@@ -31,8 +31,9 @@ import jakarta.persistence.Entity;
 import jakarta.persistence.GeneratedValue;
 import jakarta.persistence.Id;
 import jakarta.persistence.Table;
+
+import org.apache.commons.lang3.StringUtils;
 import org.dromara.maxkey.crypto.Base64Utils;
-import org.dromara.maxkey.util.StringUtils;
 
 /**
  * .
@@ -173,10 +174,12 @@ public class UserInfo extends JpaEntity  implements Serializable {
     // for work
     @Column
     protected String workCountry;
+    // province
     @Column
-    protected String workRegion;// province;
+    protected String workRegion;
+    // city
     @Column
-    protected String workLocality;// city;
+    protected String workLocality;
     @Column
     protected String workStreetAddress;
     @Column
@@ -194,10 +197,12 @@ public class UserInfo extends JpaEntity  implements Serializable {
     // for home
     @Column
     protected String homeCountry;
+    // province
     @Column
-    protected String homeRegion;// province;
+    protected String homeRegion;
+    // city
     @Column
-    protected String homeLocality;// city;
+    protected String homeLocality;
     @Column
     protected String homeStreetAddress;
     @Column
@@ -441,7 +446,7 @@ public class UserInfo extends JpaEntity  implements Serializable {
      */
     public HashMap<String, String> getProtectedAppsMap() {
         if (protectedAppsMap == null) {
-            protectedAppsMap = new HashMap<String, String>();
+            protectedAppsMap = new HashMap<>();
         }
         if (StringUtils.isNotEmpty(protectedApps)) {
             String[] apps = protectedApps.split(",");

+ 6 - 6
maxkey-core/src/main/java/org/dromara/maxkey/entity/GroupPrivileges.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/permissions/Permission.java

@@ -15,7 +15,7 @@
  */
  
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.permissions;
 
 import java.io.Serializable;
 import org.dromara.mybatis.jpa.entity.JpaEntity;
@@ -29,8 +29,8 @@ import org.dromara.maxkey.constants.ConstsStatus;
 import org.dromara.maxkey.web.WebContext;
 
 @Entity
-@Table(name = "MXK_GROUP_PRIVILEGES")
-public class GroupPrivileges  extends JpaEntity implements Serializable {
+@Table(name = "MXK_PERMISSION")
+public class Permission  extends JpaEntity implements Serializable {
     private static final long serialVersionUID = -8783585691243853899L;
     
     @Id
@@ -50,10 +50,10 @@ public class GroupPrivileges  extends JpaEntity implements Serializable {
 
 	private String instName;
 	
-    public GroupPrivileges() {
+    public Permission() {
     }
 
-    public GroupPrivileges(String appId, String groupId, String instId) {
+    public Permission(String appId, String groupId, String instId) {
         this.appId = appId;
         this.groupId = groupId;
         this.instId = instId;
@@ -65,7 +65,7 @@ public class GroupPrivileges  extends JpaEntity implements Serializable {
      * @param groupId String
      * @param resourceId String
      */
-    public GroupPrivileges(String appId, String groupId, String resourceId , String instId) {
+    public Permission(String appId, String groupId, String resourceId , String instId) {
         this.id = WebContext.genId();
         this.appId = appId;
         this.groupId = groupId;

+ 185 - 0
maxkey-core/src/main/java/org/dromara/maxkey/entity/permissions/PermissionRole.java

@@ -0,0 +1,185 @@
+/*
+ * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+ 
+
+package org.dromara.maxkey.entity.permissions;
+
+import java.io.Serializable;
+
+import org.dromara.maxkey.constants.ConstsStatus;
+import org.dromara.maxkey.web.WebContext;
+import org.dromara.mybatis.jpa.entity.JpaEntity;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+
+@Entity
+@Table(name = "MXK_PERMISSION_ROLE")
+public class PermissionRole  extends JpaEntity implements Serializable {
+    private static final long serialVersionUID = -8783585691243853899L;
+    
+    @Id
+    @Column
+    @GeneratedValue
+    String id;
+    @Column
+    String appId;
+    @Column
+    String roleId;
+    @Column
+    String resourceId;
+    @Column
+    String createdBy;
+    @Column
+    String createdDate;
+    
+    int status = ConstsStatus.ACTIVE;
+	@Column
+	private String instId;
+
+	private String instName;
+	
+    public PermissionRole() {
+    }
+
+    public PermissionRole(String appId, String roleId, String instId) {
+        this.appId = appId;
+        this.roleId = roleId;
+        this.instId = instId;
+    }
+    
+    /**
+     * .
+     * @param appId String
+     * @param roleId String
+     * @param resourceId String
+     */
+    public PermissionRole(String appId, String roleId, String resourceId , String createdBy,String instId) {
+        this.id = WebContext.genId();
+        this.appId = appId;
+        this.roleId = roleId;
+        this.resourceId = resourceId;
+        this.createdBy = createdBy;
+        this.instId = instId;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
+    public String getRoleId() {
+        return roleId;
+    }
+
+    public void setRoleId(String roleId) {
+        this.roleId = roleId;
+    }
+
+    public String getResourceId() {
+        return resourceId;
+    }
+
+    public void setResourceId(String resourceId) {
+        this.resourceId = resourceId;
+    }
+
+    public int getStatus() {
+        return status;
+    }
+
+    public void setStatus(int status) {
+        this.status = status;
+    }
+    
+    public String  getUniqueId() {
+        return  appId + "_" + roleId + "_" + resourceId;
+    }
+
+    public String getCreatedBy() {
+		return createdBy;
+	}
+
+	public void setCreatedBy(String createdBy) {
+		this.createdBy = createdBy;
+	}
+
+	public String getCreatedDate() {
+		return createdDate;
+	}
+
+	public void setCreatedDate(String createdDate) {
+		this.createdDate = createdDate;
+	}
+
+	public String getInstId() {
+		return instId;
+	}
+
+	public void setInstId(String instId) {
+		this.instId = instId;
+	}
+
+	public String getInstName() {
+		return instName;
+	}
+
+	public void setInstName(String instName) {
+		this.instName = instName;
+	}
+
+	@Override
+	public String toString() {
+		StringBuilder builder = new StringBuilder();
+		builder.append("PermissionRole [id=");
+		builder.append(id);
+		builder.append(", appId=");
+		builder.append(appId);
+		builder.append(", roleId=");
+		builder.append(roleId);
+		builder.append(", resourceId=");
+		builder.append(resourceId);
+		builder.append(", createdBy=");
+		builder.append(createdBy);
+		builder.append(", createdDate=");
+		builder.append(createdDate);
+		builder.append(", status=");
+		builder.append(status);
+		builder.append(", instId=");
+		builder.append(instId);
+		builder.append(", instName=");
+		builder.append(instName);
+		builder.append("]");
+		return builder.toString();
+	}
+    
+
+}

+ 1 - 1
maxkey-core/src/main/java/org/dromara/maxkey/entity/Resources.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/permissions/Resources.java

@@ -15,7 +15,7 @@
  */
  
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.permissions;
 
 import java.io.Serializable;
 import java.util.Date;

+ 13 - 4
maxkey-core/src/main/java/org/dromara/maxkey/entity/RoleMember.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/permissions/RoleMember.java

@@ -15,11 +15,11 @@
  */
  
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.permissions;
 
 import java.io.Serializable;
 
-import org.dromara.mybatis.jpa.entity.JpaEntity;
+import org.dromara.maxkey.entity.idm.UserInfo;
 
 import jakarta.persistence.Column;
 import jakarta.persistence.Entity;
@@ -48,6 +48,8 @@ public class RoleMember extends UserInfo implements Serializable{
 	private String memberName;
 	@Column
 	private String type;//User or Group
+	
+	private String createdBy;
 
 	@Column
 	private String instId;
@@ -73,14 +75,14 @@ public class RoleMember extends UserInfo implements Serializable{
 	}
 
 
-	public RoleMember(String roleId, String roleName, String memberId,
-			String memberName, String type , String instId) {
+	public RoleMember(String roleId, String roleName, String memberId,String memberName, String type , String createdBy, String instId) {
 		super();
 		this.roleId = roleId;
 		this.roleName = roleName;
 		this.memberId = memberId;
 		this.memberName = memberName;
 		this.type = type;
+		this.createdBy = createdBy;
 		this.instId = instId;
 	}
 
@@ -164,6 +166,13 @@ public class RoleMember extends UserInfo implements Serializable{
 		this.category = category;
 	}
 
+	public String getCreatedBy() {
+		return createdBy;
+	}
+
+	public void setCreatedBy(String createdBy) {
+		this.createdBy = createdBy;
+	}
 
 	public String getInstId() {
 		return instId;

+ 14 - 27
maxkey-core/src/main/java/org/dromara/maxkey/entity/Roles.java → maxkey-core/src/main/java/org/dromara/maxkey/entity/permissions/Roles.java

@@ -15,7 +15,7 @@
  */
  
 
-package org.dromara.maxkey.entity;
+package org.dromara.maxkey.entity.permissions;
 
 import java.io.Serializable;
 import java.util.Date;
@@ -43,7 +43,6 @@ public class Roles extends JpaEntity implements Serializable {
     	public static final String APP     = "app";
     }
     
-    
     @Id
     @Column
     @GeneratedValue
@@ -65,10 +64,6 @@ public class Roles extends JpaEntity implements Serializable {
     
     @Column
     String orgIdsList;
-    @Column
-    String resumeTime; 
-    @Column
-    String suspendTime;
     
     @Column
     int isdefault;
@@ -85,6 +80,9 @@ public class Roles extends JpaEntity implements Serializable {
     @Column
     int status;
     
+    @Column
+    String appId;
+    
 	@Column
 	private String instId;
 
@@ -103,12 +101,13 @@ public class Roles extends JpaEntity implements Serializable {
      * @param name String
      * @param isdefault int
      */
-    public Roles(String id,String roleCode, String roleName, int isdefault) {
+    public Roles(String id,String roleCode, String roleName, int isdefault,String appId) {
         super();
         this.id = id;
         this.roleCode = roleCode;
         this.roleName = roleName;
         this.isdefault = isdefault;
+        this.appId = appId;
     }
 
 	public String getId() {
@@ -198,7 +197,7 @@ public class Roles extends JpaEntity implements Serializable {
 	 *		3, not filters
      */
     public void setDefaultAllUser() {
-    	this.category = "dynamic";
+    	this.category = Category.DYNAMIC;
     	this.orgIdsList ="";
 		this.filters ="";
     }
@@ -227,23 +226,15 @@ public class Roles extends JpaEntity implements Serializable {
         this.orgIdsList = orgIdsList;
     }
 
-    public String getResumeTime() {
-        return resumeTime;
-    }
-
-    public void setResumeTime(String resumeTime) {
-        this.resumeTime = resumeTime;
-    }
-
-    public String getSuspendTime() {
-        return suspendTime;
-    }
+    public String getAppId() {
+		return appId;
+	}
 
-    public void setSuspendTime(String suspendTime) {
-        this.suspendTime = suspendTime;
-    }
+	public void setAppId(String appId) {
+		this.appId = appId;
+	}
 
-    public String getInstId() {
+	public String getInstId() {
 		return instId;
 	}
 
@@ -274,10 +265,6 @@ public class Roles extends JpaEntity implements Serializable {
 		builder.append(filters);
 		builder.append(", orgIdsList=");
 		builder.append(orgIdsList);
-		builder.append(", resumeTime=");
-		builder.append(resumeTime);
-		builder.append(", suspendTime=");
-		builder.append(suspendTime);
 		builder.append(", isdefault=");
 		builder.append(isdefault);
 		builder.append(", description=");

+ 64 - 0
maxkey-core/src/main/java/org/dromara/maxkey/exception/BusinessException.java

@@ -0,0 +1,64 @@
+/*
+ * Copyright [2024] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.dromara.maxkey.exception;
+
+import java.io.Serial;
+
+/**
+ * @description:
+ * @author: orangeBabu
+ * @time: 16/8/2024 PM3:03
+ */
+public class BusinessException extends RuntimeException {
+    /**
+     * 异常编码
+     */
+    private Integer code;
+
+    /**
+     * 异常消息
+     */
+    private String message;
+
+
+    public BusinessException() {
+        super();
+    }
+
+    public BusinessException(Integer code, String message) {
+        this.message = message;
+        this.code = code;
+    }
+
+    public Integer getCode() {
+        return code;
+    }
+
+    public void setCode(Integer code) {
+        this.code = code;
+    }
+
+    @Override
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+}

Some files were not shown because too many files changed in this diff