keyclock==纯java实现第三方登录

官网Guides - Keycloak

下载 Downloads 18.0.0 - Keycloak  

GitHub:  https://github.com/keycloak/keycloak/tags?after=17.0.1

=============================

1-安装启动

 参照readme文件

启动

bin\kc.bat start-dev

初始化超管账号密码admin admin

keyclock==纯java实现第三方登录_第1张图片

 keyclock==纯java实现第三方登录_第2张图片

参考官方教程  OpenJDK - Keycloak 

打开超管界面http://localhost:8080/admin

keyclock==纯java实现第三方登录_第3张图片

创建realm

keyclock==纯java实现第三方登录_第4张图片

keyclock==纯java实现第三方登录_第5张图片

 往realm中添加用户myuser,并设置密码为test

keyclock==纯java实现第三方登录_第6张图片

keyclock==纯java实现第三方登录_第7张图片

keyclock==纯java实现第三方登录_第8张图片 激活myuser

keyclock==纯java实现第三方登录_第9张图片

 登录myuser的界面http://localhost:8080/realms/myrealm/account

 可以看到myuser自己的一些信息keyclock==纯java实现第三方登录_第10张图片

keyclock==纯java实现第三方登录_第11张图片

 ===============================================

2-对接一个项目

打开ADMIN页面配置

keyclock==纯java实现第三方登录_第12张图片

keyclock==纯java实现第三方登录_第13张图片

keyclock==纯java实现第三方登录_第14张图片

 打开官网的测试网站Test application - Keycloak

 根据官方教程就发现登录成功并且回调回来了。

============================================================

3-自己用java代码实现

打开F12观察刚才官方教程浏览器的认证回调的请求,自己照着写:

第一步拉起登录页面

package com.example.demokeycloak2;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    //    private static final String KEYCLOAK_LOGIN_URL = "http://keycloak-server/auth/realms/your-realm/protocol/openid-connect/auth";
    private static final String KEYCLOAK_LOGIN_URL = "http://localhost:8080/realms/myrealm/protocol/openid-connect/auth";
    private static final String CLIENT_ID = "myclient";
    private static final String REDIRECT_URI = "http://localhost:8081/callback"; // 替换为你的应用程序的回调 URL

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 生成 Keycloak 登录的 URL
        String keycloakLoginURL = KEYCLOAK_LOGIN_URL +
                "?client_id=" + CLIENT_ID +
                "&redirect_uri=" + REDIRECT_URI +
                "&response_type=code";

        // 重定向到 Keycloak 登录页面
        response.sendRedirect(keycloakLoginURL);
    }
}

第二步手动在登录页面输入账号密码

keyclock==纯java实现第三方登录_第15张图片

第三步认证成功,回调到callback

package com.example.demokeycloak2;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

@WebServlet("/callback")
public class CallbackServlet extends HttpServlet {
    private static final String TOKEN_ENDPOINT = "http://localhost:8080/realms/myrealm/protocol/openid-connect/token";
    private static final String CLIENT_ID = "myclient";
    private static final String REDIRECT_URI = "http://localhost:8081/callback"; // 替换为你的应用程序的回调 URL

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String code = request.getParameter("code"); // 获取授权码
        String error = request.getParameter("error"); // 检查是否有错误信息

        if (error != null) {
            // 处理错误情况
            response.getWriter().println("登录失败:" + error);
        } else if (code != null) {
            // 使用授权码获取访问令牌
            String accessToken = getAccessToken(code);
            if (accessToken != null) {
                System.out.println("accessToken");
                System.out.println(accessToken);
                // 在此处执行你的业务逻辑,例如获取用户信息或访问受保护的资源
                // ...

                // 示例:重定向到用户仪表板页面
//                response.sendRedirect("/dashboard");
                response.setContentType("text/html");

                // Hello
                PrintWriter out = response.getWriter();
                out.println("");
                out.println("

" + "hello:" + accessToken + "

"); out.println(""); } else { // 获取访问令牌失败 response.getWriter().println("获取访问令牌失败"); } } else { // 无效的请求,缺少授权码或错误信息 response.getWriter().println("无效的请求"); } } private String getAccessToken(String code) throws IOException { // 构建获取访问令牌的请求参数 String requestBody = "grant_type=authorization_code" + "&client_id=" + CLIENT_ID + "&code=" + code + "&redirect_uri=" + REDIRECT_URI; // 发送获取访问令牌的请求 HttpURLConnection connection = null; try { URL url = new URL(TOKEN_ENDPOINT); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("POST"); connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); connection.setDoOutput(true); try (OutputStream outputStream = connection.getOutputStream()) { outputStream.write(requestBody.getBytes()); } int responseCode = connection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { // 读取响应 try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { StringBuilder responseBuilder = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { responseBuilder.append(line); } String responseJson = responseBuilder.toString(); System.out.println("responseJson"); System.out.println(responseJson); // 解析响应 JSON,提取访问令牌 return extractAccessToken(responseJson); } } else { // 获取访问令牌失败 return null; } } finally { if (connection != null) { connection.disconnect(); } } } private String extractAccessToken(String token) { // 解析 JSON 提取访问令牌的逻辑 // 这里需要根据 Keycloak 返回的 JSON 结构进行解析 // 返回访问令牌字符串 JSONObject jsonObject = (JSONObject) JSON.parse(token); String content = jsonObject.get("access_token").toString(); System.out.println(content); String s = content.split("\\.")[1]; //解码 Base64.Decoder decoder = Base64.getDecoder(); System.out.println("access_token"); System.out.println(new String(decoder.decode(s), StandardCharsets.UTF_8)); return new String(decoder.decode(s), StandardCharsets.UTF_8); } }

显然也需要将回调地址和来源地址在超管控制台加上,同时注意access type为public这样才能不使用client secret来获取到access token

keyclock==纯java实现第三方登录_第16张图片

keyclock==纯java实现第三方登录_第17张图片

 项目的根路径也要改成/

keyclock==纯java实现第三方登录_第18张图片

成功获取到用户信息name等

keyclock==纯java实现第三方登录_第19张图片

你可能感兴趣的:(java)