几年前出于兴趣,写了第一个 Keycloak 微信公众号关注即登录插件,后来不断扩展,又支持了微信扫码登录。接着又折腾了一个企业微信登录,再接着又如法炮制,分别搞了个钉钉登录、手机验证码登录等等。
这些除了钉钉登录是完全自建外,其他的几个其实都是基于别人的方案做了些魔改而已,并发布到了 GitHub 的包管理中心。
详见:
- 《基于 keycloak 的关注公众号即登录功能的设计与实现 - Jeff Tian的文章 - 知乎 》
- 《【继续更新】尝试在 Keycloak 里打通整个微信生态 - Jeff Tian的文章 - 知乎 》
- 《三步开发社交账号登录(以钉钉登录举例) - Jeff Tian的文章 - 知乎 》
- 《多因素身份认证之在 Keycloak 里集成短信注册登录实战 - Jeff Tian的文章 - 知乎 》
发布到 GitHub 的包管理中心非常简单,只需要配置如下 GitHub Actions 即可:
yaml name: Maven Package
on: release: types: [released]
workflow_run: workflows: [ Release Workflow ] branches: [ master ] types: - completed
jobs: build-and-publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 18
uses: actions/setup-java@v4
with:
java-version: 18
distribution: adopt
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
- name: Test
run: mvn clean test
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Publish to GitHub Packages Apache Maven
run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml
env:
GITHUB_TOKEN: ${{ github.token }}
将 jar 包发布在 GitHub 包管理中心虽然方便,但是它是一个默认非公开的集中包管理中心,即使用时,需要使用令牌验证。我的这些包,都是希望公开给所有人使用的,所以我创建了一个令牌,并且公开写在 ReadMe 文件中。比如要使用微信登录插件,就先在 pom.xml 中添加我的包管理源:
xml
然后,添加相关的依赖:
xml
<dependency>
<groupId>io.github.jeff-tian</groupId>
<artifactId>keycloak-services-social-weixin</artifactId>
<version>0.5.36</version>
</dependency>
下载依赖时,需要配置环境变量:GH_TOKEN=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,比如:
shell GH_TOKEN=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 mvn install
这样,就可以了。虽然可以,但是却不够方便,最讨厌的一点是,GitHub 会扫描泄露的令牌,我将该令牌共享出来后,有可能会扫描到,从而 GitHub 会强制该令牌失效,导致用户又不能正常下载了。我看了 GitHub 的文档,似乎没有办法将发布到 GitHub 上的包设置为公开。
于是,我决定将这些包发布到 Maven Central,这样,使用者就什么都不用配置,便可以直接下载使用。下了决心,于是一口气就将以上4个插件全都发到 Maven Central 了,希望给大家使用带来尽可能多的方便!
同时,本文后半部分记录一下我将它们发布到 Maven Central 的过程,不得不说,比发布到 GitHub 还是多了很多工作量的,但是带来的收益肯定能够值回票价。
成为 sonatype 的用户
要将自己的 jar 包发布到 Maven Central,首先需要成为 sonatype 的用户,我使用 GitHub 登录了 sonatype,自动获得了一个认证的命名空间: io.github.jeff-tian。
修改 pom.xml
检查 pom.xml,确保具有:
- 认证通过的命名空间
- 项目 URL 等元信息
- 源代码元信息
- 作者元信息
- 许可证元信息
- profile
以下两个典型的提交可以展示是如何添加以上信息的:
- https://github.com/Jeff-Tian/keycloak-services-social-dingding/commit/30b32abf0c42f10645c94e10625300bba9983ad7
- https://github.com/Jeff-Tian/keycloak-services-social-dingding/commit/d63abe61789d6e76270b55f8361f8a6be4eaddf0
即做这样的改动:
xml
<developers>
<developer>
<id>jeff-tian</id>
<name>Jeff Tian</name>
<email>jeff.tian@outlook.com</email>
<url>https://jefftian.dev</url>
</developer>
</developers>
<scm>
<url>https://github.com/jeff-tian/keycloak-services-social-dingding</url>
<connection>scm:git:git://github.com/jeff-tian/keycloak-services-social-dingding.git</connection>
<developerConnection>scm:git:ssh://github.com/jeff-tian/keycloak-services-social-dingding.git</developerConnection>
<tag>HEAD</tag>
</scm>
<developers>
<developer>
<id>jeff-tian</id>
<name>Jeff Tian</name>
<email>jeff.tian@outlook.com</email>
<url>https://jefftian.dev</url>
</developer>
</developers>
<scm>
<url>https://github.com/jeff-tian/keycloak-services-social-dingding</url>
<connection>scm:git:git://github.com/jeff-tian/keycloak-services-social-dingding.git</connection>
<developerConnection>scm:git:ssh://github.com/jeff-tian/keycloak-services-social-dingding.git</developerConnection>
<tag>HEAD</tag>
</scm>
向代码仓库添加需要的秘密值
一共需要向需要发布到 Maven Central 的代码仓库中添加 4 个秘密值,如下所示:
让我们来一一分解。
CENTRAL_TOKEN_USERNAME 和 CENTRAL_TOKEN_PASSWORD
成为 sonatype 的用户之后,可以去申请令牌用户和令牌密码,以供在发布 jar 包环节,调用 sonatype 的 API 时进行身份认证。
这两个值是在 https://central.sonatype.com/account 页面进行申请的:
GPG_SIGNING_KEY
这是在 mvn deploy时进行对代码文件进行 GPG 签名时需要的秘钥,记住,必须使用如下命令将其值拷贝下来,并粘贴到 GitHub Actions 秘密值中:
shell gpg --armor export-secert-keys <你的ID>
这一步其实卡了我很久很久,详见 https://github.com/actions/setup-java/issues/675 。
后面我们会在 GitHub Actions 中通过 setup-java来进行 GPG 密钥导入。如果密钥值不对,这一步会报错。然而,我不小心使用了这个命令: gpg --armor --export <你的ID>来获取了 GPG 密钥值,并粘贴到了 GitHub Actions 中的秘密值中,结果是 setup-java显示成功地导入了 GPG 密钥,但是最后却在 mvn deploy对代码文件进行签名时说找不到密钥。这就让人非常困惑,特此提醒,一定要用 gpg --armor export-secret-keys,以免踩坑!
MAVEN_GPG_PASSPHRASE
这是能够打开你的 GPG 密钥的密码,你在上一步进行 gpg --armor export-secret-keys导出密钥时,就会被询问该密码。
通过 GitHub Actions 自动发布到 Maven Central
我希望达到的目标是,提交代码,自动运行测试做个检查。如果没有问题,并且版本号有更新,就自动创建发布目标。在发布目标生成后,就自动发布到 Maven Central。这么一套流程,就需要 3 个 GitHub Actions,分别创建3个文件来实现,以下直接给出源码,懒得一一解释了。也可以直接打开 https://github.com/Jeff-Tian/keycloak-services-social-dingding/tree/main/.github/workflows 查看在线源码。
maven.yml
这就在提交代码后运行自动化测试的工作流:
yaml
This workflow will build a Java project with Maven
For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Java CI with Maven
on: push: pull_request:
jobs: build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 18
uses: actions/setup-java@v1
with:
java-version: 18
- name: Test
run: mvn clean test
- name: Build with Maven
run: mvn -B package --file pom.xml
# 上传生成的文件作为 Artifact
- name: Upload Maven package
uses: actions/upload-artifact@v4
with:
name: java-artifacts
path: target/
release.yml
这是在 GitHub 上创建出发布版本的工作流:
yaml name: Release Workflow
on: workflow_run: workflows: [ Java CI with Maven ] branches: [ main ] types: - completed
jobs: release: name: Release Process runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Download Java CI with Maven artifacts
uses: actions/download-artifact@v4
with:
name: java-artifacts
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
- name: Set up JDK 18
uses: actions/setup-java@v2
with:
distribution: adopt
java-version: 18
- name: Get latest tag
id: get_latest_tag
run: |
git fetch --tags
tag_commit=$(git rev-list --tags --max-count=1)
if [ -z $tag_commit ]; then
latest_tag=0.0.0
else
latest_tag=$(git describe --tags $tag_commit)
fi
echo ::set-output name=latest_tag::$latest_tag
- name: Get current version from pom.xml
id: get_current_version
run: |
current_version=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
echo ::set-output name=current_version::$current_version
- name: Check if pom.xml version has changed
id: check_version
run: |
if [ ${{ steps.get_current_version.outputs.current_version }} != ${{ steps.get_latest_tag.outputs.latest_tag }} ]; then
echo Version changed
echo ::set-output name=version_changed::true
else
echo Version not changed
echo ::set-output name=version_changed::false
fi
- name: Create and Push Tag
id: push_tag
if: steps.check_version.outputs.version_changed == true
run: |
git config --local user.email action@github.com
git config --local user.name GitHub Action
git tag -a ${{ steps.get_current_version.outputs.current_version }} -m Generated tag from GitHub Actions
git push origin ${{ steps.get_current_version.outputs.current_version }}
ls -al
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create release
id: create_release
if: steps.check_version.outputs.version_changed == true
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.get_current_version.outputs.current_version }}
release_name: Release ${{ steps.get_current_version.outputs.current_version }}
draft: false
prerelease: false
mavenpublish.yml
这是在版本创建出来后,自动向 GitHub 和 Maven Central 发布 jar 包的工作流:
yaml name: Maven Package
on: release: types: [ released ]
workflow_run: workflows: [ Release Workflow ] branches: [ main ] types: - completed
jobs: build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 18
uses: actions/setup-java@v1
with:
java-version: 18
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
- name: Get latest tag
id: get_latest_tag
run: |
git fetch --tags
tag_commit=$(git rev-list --tags --max-count=1)
if [ -z $tag_commit ]; then
latest_tag=0.0.0
else
latest_tag=$(git describe --tags $tag_commit)
fi
echo ::set-output name=latest_tag::$latest_tag
- name: Get current version from pom.xml
id: get_current_version
run: |
current_version=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
echo ::set-output name=current_version::$current_version
- name: Check if pom.xml version has changed
id: check_version
run: |
if [ ${{ steps.get_current_version.outputs.current_version }} != ${{ steps.get_latest_tag.outputs.latest_tag }} ]; then
echo Version changed
echo ::set-output name=version_changed::true
else
echo Version not changed
echo ::set-output name=version_changed::false
fi
- name: Test
if: steps.check_version.outputs.version_changed == true
run: mvn clean test
- name: Build with Maven
if: steps.check_version.outputs.version_changed == true
run: mvn -B package --file pom.xml
- name: Publish to GitHub Packages Apache Maven
if: steps.check_version.outputs.version_changed == true
run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml
env:
GITHUB_TOKEN: ${{ github.token }}
publish-to-maven-central: needs: [ build ] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Maven Central Repository uses: actions/setup-java@v4 with: java-version: 18 distribution: adopt server-id: central server-username: MAVEN_USERNAME server-password: MAVEN_PASSWORD gpg-private-key: ${{ secrets.GPG_SIGNING_KEY }} gpg-passphrase: MAVEN_GPG_PASSPHRASE
- name: Set Version
run: mvn versions:set -DnewVersion=${{ github.event.release.tag_name }}
- name: Publish to Maven Central
run: |
mvn -P release --batch-mode deploy -DskipTests
env:
MAVEN_USERNAME: ${{ secrets.CENTRAL_TOKEN_USERNAME }}
MAVEN_PASSWORD: ${{ secrets.CENTRAL_TOKEN_PASSWORD }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
验证
为了验证已经发布的 jar 包,我在 https://github.com/Jeff-Tian/keycloak-heroku 中删除了 GitHub repo 定义,直接在 pom.xml 中添加这几个包:
yaml
<dependency>
<groupId>io.github.jeff-tian</groupId>
<artifactId>keycloak-services-social-weixin</artifactId>
<version>0.5.36</version>
</dependency>
<dependency>
<groupId>io.github.jeff-tian</groupId>
<artifactId>keycloak-services-social-dingding</artifactId>
<version>0.0.4</version>
</dependency>
<dependency>
<groupId>io.github.jeff-tian</groupId>
<artifactId>keycloak-services-social-wechat-work</artifactId>
<version>22.0.6</version>
</dependency>
<dependency>
<groupId>io.github.jeff-tian</groupId>
<artifactId>keycloak-phone-provider</artifactId>
<version>2.3.10</version>
</dependency>
<dependency>
<groupId>io.github.jeff-tian</groupId>
<artifactId>keycloak-phone-provider.resources</artifactId>
<version>2.3.10</version>
</dependency>
<dependency>
<groupId>io.github.jeff-tian</groupId>
<artifactId>keycloak-sms-provider-dummy</artifactId>
<version>2.3.10</version>
</dependency>
本地 mvn install没有任何问题,部署到 keycloak.jiwai.win 之后的效果如下:
也可以通过 GitHub 的 Code Space 打开,然后在命令行中执行:
yaml docker compose -f docker-compose.heroku.yml up
然后就会有端口映射成功:
链接打开后如下:
在线体验
比如可以通过点击 https://keycloak.jiwai.win/realms/UniHeart/account 这个链接,选择不同的登录方式进行体验。