JA Plus 开发者文档 JA Plus 开发者文档
首页
📖 白皮书 (opens new window)
  • 名词解释
  • 快速开始

    • 使用jap-simple
    • 使用jap-social
    • 使用jap-oauth2
    • 使用jap-oidc
    • 使用jap-sso
    • 使用jap-mfa
    • 使用jap-http-api
    • 使用jap-ldap
    • 错误代码
  • IDS

    • 简介
    • 快速开始
    • 自定义scope
    • 自定义登录页面
    • 自定义确认授权页面
    • 自定义缓存
    • 自定义Token加密密钥
    • 使用PKCE模式
    • 自动授权
    • 错误代码
  • starter

    • jap-spring-boot-starter
    • jap-simple-spring-boot-starter
    • jap-social-spring-boot-starter
    • jap-oauth2-spring-boot-starter
    • jap-oidc-spring-boot-starter
  • jap-ids的demo
  • 前后端分离架构中使用JAP
  • SpringBoot中使用JAP
  • 问题反馈
  • 项目问题
  • 异常问题
  • 功能问题
  • 数据看板🔥
  • 贡献指南
  • 行为准则
  • 用户权益
  • 贡献者们
  • 社区配套 (opens new window)
  • 教程
  • 投稿
  • 资讯
  • 关于
  • 友情链接
  • 捐赠列表
  • 其他开源
  • 更新记录
收藏
GitHub (opens new window)

FuJie Team

以开源的形式赋能开发者. Just auth into any app.
首页
📖 白皮书 (opens new window)
  • 名词解释
  • 快速开始

    • 使用jap-simple
    • 使用jap-social
    • 使用jap-oauth2
    • 使用jap-oidc
    • 使用jap-sso
    • 使用jap-mfa
    • 使用jap-http-api
    • 使用jap-ldap
    • 错误代码
  • IDS

    • 简介
    • 快速开始
    • 自定义scope
    • 自定义登录页面
    • 自定义确认授权页面
    • 自定义缓存
    • 自定义Token加密密钥
    • 使用PKCE模式
    • 自动授权
    • 错误代码
  • starter

    • jap-spring-boot-starter
    • jap-simple-spring-boot-starter
    • jap-social-spring-boot-starter
    • jap-oauth2-spring-boot-starter
    • jap-oidc-spring-boot-starter
  • jap-ids的demo
  • 前后端分离架构中使用JAP
  • SpringBoot中使用JAP
  • 问题反馈
  • 项目问题
  • 异常问题
  • 功能问题
  • 数据看板🔥
  • 贡献指南
  • 行为准则
  • 用户权益
  • 贡献者们
  • 社区配套 (opens new window)
  • 教程
  • 投稿
  • 资讯
  • 关于
  • 友情链接
  • 捐赠列表
  • 其他开源
  • 更新记录
收藏
GitHub (opens new window)
  • 教程

  • 投稿

    • 博客投稿栏目说明
    • 经验分享

      • 项目经验分享:在 JustAuth Plus 中添加 HTTP API 的登陆方式
      • 项目经验分享:开发 JuatAuth Plus 的 springboot starter 依赖包
      • 经验总结:关于为 JAP 开发不同语言的 Demo 的总结
        • 前言
        • 社区简介
        • 项目介绍
        • OAuth2.0协议
        • OIDC协议
        • 放在最后
        • 参考文献
    • 框架集成

  • 资讯

  • 博客
  • 投稿
  • 经验分享
吴豪琪
2021-11-02

经验总结:关于为 JAP 开发不同语言的 Demo 的总结

# 经验总结:关于为 JAP 开发不同语言的 Demo 的总结

# 前言

各位参与开源的导师、同学们,大家好,我是来自四川成都的一名准大三学生,怀着忐忑的心情在大二暑假前向 JustAuth (opens new window)社区提交了简历,很荣幸成功参与进人生中的第一次开源软件计划。下面由我简单分享一下此次的开源项目经验。

# 社区简介

JustAuth开源社区 (opens new window), 致力于为开源的授权/身份认证技术开发、布道。以开源之名,赋能开发者。名下开源项目 JustAuth 深受开发者喜欢,在 Gitee (opens new window)和 Github (opens new window)中的累计关注量近 19K,并荣获 Gitee GVP 称号,目前已有多个企业(中文在线、北京市公园管理中心、前海人寿等)、组织和开源项目(Shiro Action、sika、七腾智能、BladeX、GUNS、MaxKey、mica)正在使用 JustAuth 完成极速的第三方登录集成。

JustAuth 致力于让开发者们脱离繁琐的第三方登录SDK,简化登录开发过程,做到开箱即用

同时基于 JustAuth,结合目前流行的登录技术(OAuth 2.0,SAML、OIDC、LDAP、CAS等)又开源出了 JustAuthPlus。

JustAuthPlus (opens new window)(以下简称"JAP")于 2021-01-12 开始筹划建立,是一款开源的登录认证中间件,基于模块化设计,为所有需要登录认证的 WEB 应用提供一套标准的技术解决方案,开发者可以基于 JAP 适配绝大多数的 WEB 系统(自有系统、联邦协议)。

JAP 从 JustAuth 中衍生而出,同样做到了开箱即用的程度,至 2021-09-24,已迭代更新5个版本,添加数十种功能。JAP 高度抽象各种登录场景,提供多套简单实用的 API,高度注重登录认证的安全性,为每一种登录场景(与开发语言无关)都提供了独有的模块化解决方案,支持 Form、 Auth2.0、OIDC、Http Basic、Digest、Bearer、LDAP、SAML、MFA、SSO 等。开发设计至今已有中文在线,符节科技,六牛科技,Mica 等多家企业/组织使用。已于2021年9月荣获 **GVP(码云最具有价值开源项目)**称号。

截止目前,JustAuth 和 JustAuthPlus 项目收藏量已接近 20K 左右,项目关注量持续增加。

JAP 功能模块说明:

详情:前往 (opens new window)

image-20211029160750814

# 项目介绍

项目名称:完成 JFinal、Blade、ActFramework 框架集成 JustAuthPlus 的 demo

项目仓库:

  • GitHub:
    • 后端:https://github.com/fujieid/jap-jfinal-blade-actframework-demo
    • 前端:https://github.com/fujieid/jap-jfinal-blade-actframework-demo/tree/VuePro
tips:根据该项目的产出要求,JAP的实现过程,已在后端代码进行了大致解释。

此次开发我个人采用的是在合理的时间规划后,以前后端分离方式开发实现 第三方登录,OAuth2登录,OIDC登录,账号密码登录这几种登录方式。此次以后端的OAuth2和OIDC登录为主要分享经验。 以面向小白为主,我以浅显易懂的方式编写这篇文章,希望能够有所学有所思有所用。

  1. 什么是OAuth2.0?
  2. 什么是OIDC?
  3. 什么是令牌Token?
  4. 什么是CSRF?
  5. 什么是PKCE?有何作用?
  6. JAP如何做到开箱即用,如何简化开发者开发设计?

等等,以上这些都是基础程序员必须需要了解和掌握的基础知识。

# OAuth2.0协议

官方定义:

The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, either on behalf of a resource owner by orchestrating an approval interaction between the resource owner and the HTTP service, or by allowing the third-party application to obtain access on its own behalf.This specification replaces and obsoletes the OAuth 1.0 protocol described in RFC 5849.
1

简单来说就是一种授权机制(协议),形象化地说就是他人(第三方)需要进入资源区获得资源,而设立的一个中间屏障(授权层),用于验证第三方身份的安全性和保护资源的安全使用。而在能够成功使用资源这一目的之前,需要经过多次的身份验证和授权。结合一位经验丰富的取货人需要去仓库负责人处拿到入库取货凭证,并到仓库运货为例。注:取货人是该仓库的一名帮工,并之前已经登记注册帮工名单。

下面简单介绍在这验证授权期间使用的4个专有名词:

  • client:An application making protected resource requests on behalf of the resource owner and with its authorization.关键字:一个应用程序、资源请求、已被资源所有者授权。例如“取货人”,需要向仓库负责人请示:是否自己有任务去仓库取货。

  • resource owners:An entity capable of granting access to a protected resource. When the resource owner is a person, it is referred to as an end-user.关键字:接收授权请求,授权entity ,访问保护资源。例如“仓库负责人”,需要对取货人的请示进行验证:验证这个取货者是否是在帮工名册上,是否安全,若完成检查,则仓库负责人给取货人颁发一个凭证Authorization Grant 。

  • authorization server:The server issuing access tokens to the client after successfully authenticating the resource owner and obtaining authorization.关键字:接收Authorization Grant,颁发令牌Token。例如“仓库保安”,收到从取货人拿出的Authorization Grant,验证无误后,让其取货者找资源服务管理部门(该部门管理货物的搬运)。

  • resource server:The server hosting the protected resources, capable of accepting and responding to protected resource requests using access tokens.关键字:接受使用来自”仓库保安“(授权服务器)令牌Token的访问,资源请求。例如“资源服务管理部门”,取货者拿出令牌,该资源服务部门验证收到Token的有效性和安全性后,给取货者运输货物。

tips:这里请注意凭证、令牌的使用对象和作用对象。

另外,我以图例作为补充,帮助你了解这4段文字的具体含义:

image-20211029132303441

官方示例图:

image-20211029093058182

这里简单介绍什么是令牌Token?

简单来说就是用户第一次登录,服务器生成的一个字符串,以此作为客户端在进行请求的一个标志。而在以后的的请求数据,客户端只需要带上这个Token即可,不再需要每次带上用户名和密码。

Token的使用方式?

可以是你设备的MAC地址(设备唯一标识符,用于数据链路层的MAC子层)也可以是session值。

这里不展开细讲。你只需要知道,这是一个用于安全的字符串,以保证客户端和服务端的通信安全。

更细化地学习,你会知道,一个authorization grant总共有四种模式可以选择,以用于第三方获取令牌,换取受保护资源。四种模式如下:

  • Authorization Code
  • Implicit
  • Resource Owner Password Credentials
  • Client Credentials

此处只介绍Authorization Code模式,其余模式可去OAuth2.0协议rfc6749文件 (opens new window)学习。

代码分析:

第三方应用 A 由于在 Gitee 已经完成备案,获得了 clientId 和 clientSecret。

第三方应用发起授权:

image-20211028233154652
第一步:Client 确认登录,跳转 Resource Owner,请求授权码,用户确认授权。

https://gitee.com/oauth/authorize?response_type=code&redirect_uri=http://127.0.0.1:8091/oauth/code&state=bcf3c0a682877e15a0dd4d590aea8781&client_id=ec7b05fdebf7c29fbd3320b1309b34011298baf7f5ac99ca8945c7aaacfbbfa&scope=user_info

该链接这里有注意点:

  • https://gitee.com/oauth/authorize:是指用于对第三方应用进行授权的Authorization Endpoint

  • response_type=code:指进行code模式的OAuth2.0授权

  • redirect_uri:用于授权成功或者失败后的跳转地址

  • client_id:指备份应用的ID

  • scope:请求的授权范围

  • state:表示安全标志位,用来保证不是伪造的请求,始终在请求授权和响应授权的URL中作为参数;

这里简单介绍什么是伪造?即什么是CSRF?

CSRF(XSRF)又称跨站请求伪造,属于一种授权攻击行为,导致最终用户的受保护资源被攻击者使用。通常是针对客户端的重定向redirect_uri发起攻击,注入攻击者自己的授权码或访问令牌。 简单点说就是攻击者使用你的信息去访问并使用受保护资源,导致受害者出现重大损失。因此为了实现CSRF保护,客户端应该使用“state”请求参数在发起授权请求时向授权服务器传送该值,并授权成功后返回同一个status值,以保证是真正的双方在进行通信。

第二步:用户确认授权,Resource Owner响应给Client授权码code。

http://127.0.0.1:8091/oauth/code?code=c54b4dc9b5559a37ef9a24a0e76f92aa31beee666ba64a3a4f1bebc20f1cab21&state=bcf3c0a682877e15a0dd4d590aea8781

Resource Owner对请求验证成功,运行发布授权码Code,此时,你会发现携带的一个status参数与请求时的status参数值一致,以此实现CSRF保护。

第三步:Client使用授权码Code去请求Authorization Server,code有效,响应给Client一个Token。
private static AccessToken getAccessTokenOfAuthorizationCodeMode(HttpServletRequest request, OAuthConfig oAuthConfig) throws JapOauth2Exception {
   String state = request.getParameter("state");
   Oauth2Util.checkState(state, oAuthConfig.getClientId(), oAuthConfig.isVerifyState());

   String code = request.getParameter("code");
   Map<String, String> params = new HashMap<>(6);
   params.put("grant_type", Oauth2GrantType.authorization_code.name());
   params.put("code", code);
   params.put("client_id", oAuthConfig.getClientId());
   params.put("client_secret", oAuthConfig.getClientSecret());
   if (StrUtil.isNotBlank(oAuthConfig.getCallbackUrl())) {
       params.put("redirect_uri", oAuthConfig.getCallbackUrl());
   }
   if (Oauth2ResponseType.code == oAuthConfig.getResponseType() && oAuthConfig.isEnablePkce()) {
       params.put(PkceParams.CODE_VERIFIER, PkceHelper.getCacheCodeVerifier(oAuthConfig.getClientId()));
   }

   Kv tokenInfo = Oauth2Util.request(oAuthConfig.getAccessTokenEndpointMethodType(), oAuthConfig.getTokenUrl(), params);
   Oauth2Util.checkOauthResponse(tokenInfo, "Oauth2Strategy failed to get AccessToken.");

   if (!tokenInfo.containsKey("access_token")) {
       throw new JapOauth2Exception("Oauth2Strategy failed to get AccessToken." + tokenInfo.toString());
   }

   return mapToAccessToken(tokenInfo);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

Client通过Token去Resource Server请求资源,该步骤已经由JAP(上述代码)完全实现,通过拼接参数,在后端发起请求Token实现,同时实现了PKCE授权码模式。

这里简单介绍什么是PKCE?

发生时间:官方示例图中的C步。

全称:Proof Key for Code Exchange。PKCE是对Authorization Code模式更进一步的安全措施,属于一种密码学手段,保证即使在C步code等被第三方截取,也无法获取用户保护资源,达到CSRF保护。

  • 客户端:而请求参数 code_challenge 的得到方式是:客户端在请求 code 之前,准备随机生成一段字符串,保存于 code_verifier 变量,然后再将该字符串通过 SHA256 哈希和 URL-Safe 的 base 编码得到打值,存进code_challenge。才开始向授权服务器端发起请求code。
  • 授权服务器端:通过请求去保存 code_challenge 和编码处理方法。在客户端拿到 code 后,再使用 code_verifier 等作为参数请求授权服务器端。授权服务器端最终使用 code_verifier 按照 code_challenge_method方式进行编码处理,将处理得到的值与请求code时传递的code_challenge进行比较。
    • 若不同:说明在请求 code 时,遭受 CSRF 攻击,但被授权服务器端发现,用户受保护资源未被泄露。
    • 若相同:说明此次换取 token 令牌的通信,未被攻击,客户端成功拿到令牌。
tips:就算攻击者拿到 code_challenge 、code等值,也不能逆推拿到 code_verifier。

下面给出图例:

image-20211029132422552
第四步:Client使用令牌Token去请求Resource Server,Token有效,响应Client需要请求的资源,如基本的用户信息,给与第三方应用。
private JapUser getUserInfo(OAuthConfig oAuthConfig, AccessToken accessToken) throws JapOauth2Exception {
    Map<String, String> params = new HashMap<>(6);
    params.put("access_token", accessToken.getAccessToken());

    Kv userInfo = Oauth2Util.request(oAuthConfig.getUserInfoEndpointMethodType(), oAuthConfig.getUserinfoUrl(), params);

    Oauth2Util.checkOauthResponse(userInfo, "Oauth2Strategy failed to get userInfo with accessToken.");

    JapUser japUser = this.japUserService.createAndGetOauth2User(oAuthConfig.getPlatform(), userInfo, accessToken);
    if (ObjectUtil.isNull(japUser)) {
        return null;
    }
    return japUser;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

拿取用户信息:

image-20211029100105796

开发者自己需要做的操作: 配置相关接口(Authorization EndPoint和Token EndPoint等)、授权类型等

这里以使用JFinal框架为例:

JFinal官网 (opens new window)

引入依赖:

<dependency>
    <groupId>com.fujieid</groupId>
    <artifactId>jap-oauth2</artifactId>
    <version>1.0.2</version>
</dependency>
1
2
3
4
5
//OAuth2.0需要的各个配置(相应的接口、授权类型等)
private static OAuthConfig config = new OAuthConfig();
//OAuth2.0 授权策略类,用于接收重定向redirect_uri和接收code换取token,拿到用户信息等,属于JAP验证授权的最外部接口。
private  Oauth2Strategy oauth2Strategy = new Oauth2Strategy(japUserService, new JapConfig());

@ActionKey("/oauth/code/getData")
public void getBaseData(){
//获取参数,这里是为了方便测试者以页面通用的方式进行输入,而不是修改源代码。但参数clientSecret等一般很重要,实际开发下不会这样使用
        String clientId = this.getRequest().getParameter("clientId");
        String clientSecrect = this.getRequest().getParameter("clientSecret");
        String redirectURI = this.getRequest().getParameter("redirectURI");
        config.setPlatform("gitee")
                .setState(UuidUtils.getUUID())
                .setClientId(clientId)
                .setClientSecret(clientSecrect)
                .setCallbackUrl(redirectURI)
                .setAuthorizationUrl("https://gitee.com/oauth/authorize")
                .setTokenUrl("https://gitee.com/oauth/token")
                .setUserinfoUrl("https://gitee.com/api/v5/user")
                .setScopes(new String[]{"user_info"})
                .setResponseType(Oauth2ResponseType.code)
                .setGrantType(Oauth2GrantType.authorization_code)
                .setUserInfoEndpointMethodType(Oauth2EndpointMethodType.GET);
	this.renderAuth();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

redirect_uri 也将是 /oauth/code 请求接口,验证成功后,会由后端该函数接收响应,由oauth2Strategy类的authenticate函数进入,并开始由JAP在后端进行向授权服务器Authorization Server换取token,这段数据将会是JSON数据,JAP也进行了响应的映射处理,向资源服务器Resource Server 用Token换取用户信息等受保护资源。

@ActionKey("/oauth/code")
public void renderAuth() {
    String code = this.getRequest().getParameter("code");  
    JapResponse japResponse = oauth2Strategy.authenticate(config, this.getRequest(), this.getResponse());
    if (!japResponse.isSuccess()) {
        renderJson("/?error=" + URLUtil.encode(japResponse.getMessage()));
    }
    if (japResponse.isRedirectUrl()) {    
    renderJson(RetKit.ok("toAuth",(String)japResponse.getData()));
	} else {
    
   	 	JapUser japUser = (JapUser) japResponse.getData();
    	renderJson(RetKit.ok("userInfos",japUser));
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# OIDC协议

官方定义:

OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 [RFC6749] (opens new window) protocol. It enables Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.

简单点说,就在在OAuth2.0的基础之上加了一层身份层。全称:OpenID Connect,用于客户端验证用户的身份并获取用户的基本信息。详细信息可见:OIDC官方文档 (opens new window)。

此处只简单描述增加的身份层是什么?

  • 前面几个步骤和 OAuth2.0 大致相同,但在认证请求时的参数需要 scope 必须包含 OpenID 字段。
  • 当 Client 向授权服务器使用code向其 Token EndPoint 请求 Token 时,Token EndPoint 接口返回 ID Token 和 Access Token。
  • Client 校验 ID Token,并从中提取用户的身份标识符(End-User分配的唯一标识符)后,向资源服务器的UserInfo EndPoint接口请求用户信息资源,返回End-User的Claims。

官方例图:

image-20211029144421126

Jap实现:开发者在完成 OIDC 的基本配置后:OidcConfig 对象的配置,后续的授权重定向以及接收用户信息均可以由 oidcStrategy.authenticate 函数实现,其内部以及完成重定向前的各个基本配置检验、用户缓存 cache 值,完成对 issuer 的拼接 /.well-known/openid-configuration等各个操作,后续直接走向 OAuth2.0 的相关过程,简化开发者设计过程,做到开箱即用。

开发者自己需要做的操作:配置相关接口(Scopes和Issuer等)、授权类型等

这里以使用JFinal框架为例:

引入依赖:

<dependency>
   <groupId>com.fujieid</groupId>
   <artifactId>jap-oidc</artifactId>
   <version>1.0.1</version>
</dependency>
1
2
3
4
5
private OidcStrategy oidcStrategy = new OidcStrategy(japUserService, new JapConfig());
private static OidcConfig config = new OidcConfig();

@ActionKey("/oidc/getData")
public void getBaseData(){
//        获取参数,这里是为了方便测试者以页面通用的方式进行输入,而不是修改源代码。但参数clientSecret等一般很重要,实际开发下不会这样使用
     String clientId = this.getRequest().getParameter("clientId");
     String clientSecrect = this.getRequest().getParameter("clientSecret");
     String redirectURI = this.getRequest().getParameter("redirectURI");    
   // 配置 OIDC 的 Issue 链接
     config.setIssuer("https://oauth.aliyun.com")
           .setPlatform("aliyun")
           .setState(UuidUtils.getUUID())
           .setClientId(clientId)
           .setClientSecret(clientSecrect)
           .setCallbackUrl(redirectURI)
           .setScopes(new String[]{"aliuid","openid","profile"})
           .setResponseType(Oauth2ResponseType.code)
           .setGrantType(Oauth2GrantType.authorization_code);

   logger.info("拿到参数,开始准备重定向授权页面");
   this.renderAuth();
}

@ActionKey("/oidc/auth")
public void renderAuth() {

   JapResponse japResponse = oidcStrategy.authenticate(config, this.getRequest(), this.getResponse());

   if (!japResponse.isSuccess()) {
       System.out.println(japResponse.getMessage());
       renderText("/?error=" + URLUtil.encode(japResponse.getMessage()));
   }
   if (japResponse.isRedirectUrl()) {
       renderJson(RetKit.ok("toAuth",(String)japResponse.getData()));
       logger.info("授权成功");
   } else {
       JapUser japUser = (JapUser) japResponse.getData();
       Map<String,StringuserInfos = new HashMap<>();
       userInfos.put("token",japUser.getToken());
       userInfos.put("username",japUser.getUsername());
       userInfos.put("userId",japUser.getUserId());
       userInfos.put("password",japUser.getPassword());

       renderJson(RetKit.ok("userInfos",userInfos));
   }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

另外,在前端方面,在这里也有几点注意的地方:

第一点:前端项目,如何实现与多个后端项目相互通信?信息类型又是什么?如何自定义实现一个专门用于传递信息的类?

第二点:当框架支持的请求响应与JAP使用的请求响应类型不一致时,应该如何做?怎么实现结构型模式中的适配器模式?

希望读者能够有所获。

# 放在最后

总结,很感谢 JustAuth 社区张亚东导师的信任,能够让学生有机会参与此次的开源计划,在这几个月的活动中,毋庸置疑的是,学到了很多很多很多知识和从导师那里了解到了很多很多开发经验。活动虽终,开发道路仍旧前行。

其次,学习的内容有很多,从适配器模式到23种经典设计模式,从 OAuth2.0 协议到各种登录协议、安全协议及措施,从 SpringBoot 框架到 JFinal、Blade 和 ActFramework 框架,从 HTML 到 VUE 实现,从 Ajax 到 axios 跨域处理等等知识点和难解点,都一一解决和学习。从开发前构想到最终实现成果完全一致,“不辱使命” 的完成了此次的项目任务,丰富了自己开发经历与经验。

# 参考文献

OAuth2标准RFC6749文件 (opens new window)

PKCE加密RFC7636文件 (opens new window)

OIDC文档 (opens new window)

#JFinal#Blade#ActFramework#Demo
Last Updated: 2021/11/02, 22:30:21
项目经验分享:开发 JuatAuth Plus 的 springboot starter 依赖包
Jap 与 Sa-Token 结合使用

← 项目经验分享:开发 JuatAuth Plus 的 springboot starter 依赖包 Jap 与 Sa-Token 结合使用→

最近更新
01
jap-spring-boot-starter 使用帮助
10-28
02
使用jap-ldap
10-25
03
jap-simple-spring-boot-starter 模块使用帮助
10-12
更多文章>
Theme by Vdoing | Copyright © 2021-2023

友情链接:UniAdmin | 江如意的博客

Copyright © 2021-2040 FUJIE. All rights reserved. 北京符节科技有限公司版权所有 | 京ICP备2020044519号-4
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式