java從azure中讀取用戶信息

以下是用 Java 從 Azure AD 獲取用戶信息的完整實現方案,使用 Spring Boot 框架和 Microsoft 身份驗證庫 (MSAL):
?
1. 添加 Maven 依賴

<dependencies>
? ? <!-- Spring Boot Web -->
? ? <dependency>
? ? ? ? <groupId>org.springframework.boot</groupId>
? ? ? ? <artifactId>spring-boot-starter-web</artifactId>
? ? </dependency>
? ??
? ? <!-- Azure AD MSAL -->
? ? <dependency>
? ? ? ? <groupId>com.microsoft.azure</groupId>
? ? ? ? <artifactId>msal4j</artifactId>
? ? ? ? <version>1.13.3</version>
? ? </dependency>
? ??
? ? <!-- JWT 處理 -->
? ? <dependency>
? ? ? ? <groupId>com.nimbusds</groupId>
? ? ? ? <artifactId>nimbus-jose-jwt</artifactId>
? ? ? ? <version>9.25</version>
? ? </dependency>
? ??
? ? <!-- HTTP 客戶端 -->
? ? <dependency>
? ? ? ? <groupId>org.apache.httpcomponents</groupId>
? ? ? ? <artifactId>httpclient</artifactId>
? ? ? ? <version>4.5.13</version>
? ? </dependency>
</dependencies>
?

2. 配置 Azure AD 參數
在 ?application.properties??中:

# Azure AD 配置
azure.client-id=your_client_id
azure.client-secret=your_client_secret
azure.tenant-id=your_tenant_id
azure.redirect-uri=https://your-app.com/auth/redirect
azure.scope=openid profile User.Read
?

3. 控制器實現

import com.microsoft.aad.msal4j.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.net.MalformedURLException;
import java.net.URI;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;

@RestController
public class AuthController {
? ??
? ? @Value("${azure.client-id}")
? ? private String clientId;
? ??
? ? @Value("${azure.client-secret}")
? ? private String clientSecret;
? ??
? ? @Value("${azure.tenant-id}")
? ? private String tenantId;
? ??
? ? @Value("${azure.redirect-uri}")
? ? private String redirectUri;
? ??
? ? @Value("${azure.scope}")
? ? private String scope;
? ??
? ? // 第一步:生成登錄URL
? ? @GetMapping("/login")
? ? public Map<String, String> login() throws MalformedURLException {
? ? ? ? String authUrl = getAuthUrl();
? ? ? ? return Collections.singletonMap("loginUrl", authUrl);
? ? }
? ??
? ? // 第二步:處理回調
? ? @GetMapping("/auth/redirect")
? ? public Map<String, Object> handleRedirect(
? ? ? ? ? ? @RequestParam("code") String authCode,
? ? ? ? ? ? @RequestParam("state") String state
? ? ) throws Exception {
? ? ? ??
? ? ? ? // 使用授權碼獲取令牌
? ? ? ? IAuthenticationResult result = acquireToken(authCode);
? ? ? ??
? ? ? ? // 獲取用戶信息
? ? ? ? Map<String, Object> userInfo = getUserInfo(result.accessToken());
? ? ? ??
? ? ? ? // 返回用戶信息
? ? ? ? Map<String, Object> response = new HashMap<>();
? ? ? ? response.put("id_token_claims", result.idToken());
? ? ? ? response.put("user_info", userInfo);
? ? ? ??
? ? ? ? return response;
? ? }
? ??
? ? // 生成認證URL
? ? private String getAuthUrl() throws MalformedURLException {
? ? ? ? ConfidentialClientApplication app = ConfidentialClientApplication.builder(
? ? ? ? ? ? ? ? clientId, ClientCredentialFactory.createFromSecret(clientSecret))
? ? ? ? ? ? ? ? .authority("https://login.microsoftonline.com/" + tenantId)
? ? ? ? ? ? ? ? .build();
? ? ? ??
? ? ? ? AuthorizationCodeParameters parameters = AuthorizationCodeParameters.builder(
? ? ? ? ? ? ? ? authCode,?
? ? ? ? ? ? ? ? new URI(redirectUri)
? ? ? ? ? ? ).scopes(Collections.singleton(scope))
? ? ? ? ? ? ?.build();
? ? ? ??
? ? ? ? String authorizationUrl = app.getAuthorizationRequestUrl(
? ? ? ? ? ? ? ? AuthorizationRequestUrlParameters
? ? ? ? ? ? ? ? ? ? .builder(redirectUri, Collections.singleton(scope))
? ? ? ? ? ? ? ? ? ? .build()
? ? ? ? ? ? ).toString();
? ? ? ??
? ? ? ? return authorizationUrl;
? ? }
? ??
? ? // 使用授權碼獲取令牌
? ? private IAuthenticationResult acquireToken(String authCode)?
? ? ? ? throws MalformedURLException, ExecutionException, InterruptedException {
? ? ? ??
? ? ? ? ConfidentialClientApplication app = ConfidentialClientApplication.builder(
? ? ? ? ? ? ? ? clientId, ClientCredentialFactory.createFromSecret(clientSecret))
? ? ? ? ? ? ? ? .authority("https://login.microsoftonline.com/" + tenantId)
? ? ? ? ? ? ? ? .build();
? ? ? ??
? ? ? ? AuthorizationCodeParameters parameters = AuthorizationCodeParameters.builder(
? ? ? ? ? ? ? ? authCode,?
? ? ? ? ? ? ? ? new URI(redirectUri)
? ? ? ? ? ? ).scopes(Collections.singleton(scope))
? ? ? ? ? ? ?.build();
? ? ? ??
? ? ? ? return app.acquireToken(parameters).get();
? ? }
? ??
? ? // 使用訪問令牌獲取用戶信息
? ? private Map<String, Object> getUserInfo(String accessToken) {
? ? ? ? String graphEndpoint = "https://graph.microsoft.com/v1.0/me";
? ? ? ??
? ? ? ? // 使用HttpClient調用Graph API
? ? ? ? // 實際實現需要添加錯誤處理和JSON解析
? ? ? ? return fetchUserDataFromGraph(graphEndpoint, accessToken);
? ? }
? ??
? ? // 調用Microsoft Graph API的實現
? ? private Map<String, Object> fetchUserDataFromGraph(String endpoint, String accessToken) {
? ? ? ? // 這里使用HttpClient簡化實現
? ? ? ? // 實際項目使用RestTemplate或WebClient
? ? ? ??
? ? ? ? HttpGet request = new HttpGet(endpoint);
? ? ? ? request.setHeader("Authorization", "Bearer " + accessToken);
? ? ? ??
? ? ? ? try (CloseableHttpClient httpClient = HttpClients.createDefault();
? ? ? ? ? ? ?CloseableHttpResponse response = httpClient.execute(request)) {
? ? ? ? ? ??
? ? ? ? ? ? String json = EntityUtils.toString(response.getEntity());
? ? ? ? ? ? return new Gson().fromJson(json, new TypeToken<Map<String, Object>>(){}.getType());
? ? ? ? ? ??
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? throw new RuntimeException("Failed to fetch user info", e);
? ? ? ? }
? ? }
}
?

4. 安全配置類 (可選)

import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.jwk.source.RemoteJWKSet;
import com.nimbusds.jose.proc.JWSVerificationKeySelector;
import com.nimbusds.jose.proc.SecurityContext;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.proc.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.net.MalformedURLException;
import java.net.URL;

@Configuration
public class SecurityConfig {

? ? @Value("${azure.tenant-id}")
? ? private String tenantId;
? ??
? ? // 配置JWT驗證器
? ? @Bean
? ? public ConfigurableJWTProcessor<SecurityContext> jwtProcessor()?
? ? ? ? throws MalformedURLException {
? ? ? ??
? ? ? ? // Azure AD JWKS端點
? ? ? ? String jwksUrl = String.format(
? ? ? ? ? ? "https://login.microsoftonline.com/%s/discovery/v2.0/keys",?
? ? ? ? ? ? tenantId
? ? ? ? );
? ? ? ??
? ? ? ? // 設置JWT處理器
? ? ? ? DefaultJWTProcessor<SecurityContext> jwtProcessor =?
? ? ? ? ? ? new DefaultJWTProcessor<>();
? ? ? ??
? ? ? ? // 配置JWK來源
? ? ? ? JWKSource<SecurityContext> keySource =?
? ? ? ? ? ? new RemoteJWKSet<>(new URL(jwksUrl));
? ? ? ??
? ? ? ? // 配置簽名驗證
? ? ? ? JWSAlgorithm expectedJWSAlg = JWSAlgorithm.RS256;
? ? ? ? JWSVerificationKeySelector<SecurityContext> keySelector =?
? ? ? ? ? ? new JWSVerificationKeySelector<>(expectedJWSAlg, keySource);
? ? ? ??
? ? ? ? jwtProcessor.setJWSKeySelector(keySelector);
? ? ? ??
? ? ? ? // 設置JWT聲明驗證器
? ? ? ? jwtProcessor.setJWTClaimsSetVerifier(new DefaultJWTClaimsVerifier<>(
? ? ? ? ? ? new JWTClaimsSet.Builder().build(),
? ? ? ? ? ? new HashSet<>(Arrays.asList("sub", "aud", "exp", "iat"))));
? ? ? ??
? ? ? ? return jwtProcessor;
? ? }
}
?

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/85689.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/85689.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/85689.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C# 數據庫訪問與ORM框架全面指南:從ADO.NET到Entity Framework Core

在現代應用開發中&#xff0c;數據持久化是核心需求之一。作為.NET生態系統中的主力語言&#xff0c;C#提供了豐富多樣的數據庫訪問技術和工具。本文將全面探討C#中的數據庫訪問方式&#xff0c;重點介紹三種主流ORM&#xff08;對象關系映射&#xff09;框架&#xff1a;Entit…

day19 leetcode-hot100-37(二叉樹2)

104. 二叉樹的最大深度 - 力扣&#xff08;LeetCode&#xff09; 1.深度優先遍歷&#xff08;遞歸&#xff09;ps:不好理解&#xff0c;所以我一般不喜歡用遞歸 思路 典型算法&#xff0c;用遞歸求出高度&#xff0c;每次都是深度優先。 具體算法 /*** Definition for a bi…

【LLMs篇】13:LLaDA—大型語言擴散模型

欄目內容論文標題大型語言擴散模型 (Large Language Diffusion Models)核心思想提出LLaDA&#xff0c;一種基于擴散模型的LLM&#xff0c;通過前向掩碼和反向預測過程建模語言分布&#xff0c;挑戰自回歸模型&#xff08;ARM&#xff09;在LLM領域的主導地位&#xff0c;并展示…

Deepfashion2 數據集使用筆記

目錄 數據類別: 篩選類別數據: 驗證篩選前2個類別: Deepfashion2 的解壓碼 數據類別: 類別含義: Class idx類別名稱英文名稱0短上衣short sleeve top1長上衣long sleeve top2短外套short sleeve outwear3長外套long sleeve outwear4裙子skirt5褲子trousers6連衣裙dre…

Java并發編程哲學系列匯總

文章目錄 并發編程基礎并發編程進階并發編程實踐 并發編程基礎 Java并發編程基礎小結 Java線程池知識點小結 詳解JUC包下各種鎖的使用 并發編程利器Java CAS原子類全解 深入理解Java中的final關鍵字 Java并發容器深入解析&#xff1a;HashMap與ArrayList線程安全問題及解…

git 之 stash

一、git stash&#xff1a;臨時保存工作區修改 作用 將當前工作目錄和暫存區的未提交修改保存到棧中&#xff0c;并恢復工作區到上一次提交的干凈狀態。 適用場景&#xff1a; 臨時切換分支修復緊急 Bug拉取遠程代碼前清理工作區保存實驗性代碼避免生成無效提交 常用命令&am…

vxe-grid 雙擊行,打開expand的內容

1、官網api Vxe Table v4.6&#xff08;根據版本&#xff09; 要調用這個事件&#xff0c;雙擊單元格&#xff0c;我們打開type"expand"的內容 2、打開的事件toggleRowExpand 3、事件的說明 這個方法&#xff0c;會自動判斷當前展開的狀態&#xff0c;然后去觸發相…

Java Stream 高級實戰:并行流、自定義收集器與性能優化

一、并行流深度實戰&#xff1a;大規模數據處理的性能突破 1.1 并行流的核心應用場景 在電商用戶行為分析場景中&#xff0c;需要對百萬級用戶日志數據進行實時統計。例如&#xff0c;計算某時段內活躍用戶數&#xff08;訪問次數≥3次的用戶&#xff09;&#xff0c;傳統循環…

計算機系統結構-第5章-監聽式協議

監聽式協議******&#xff1a; 思想: 每個Cache除了包含物理存儲器中塊的數據拷貝之外&#xff0c;也保存著各個塊的共享狀態信息。 Cache通常連在共享存儲器的總線上&#xff0c;當某個Cache需要訪問存儲器時&#xff0c;它會把請求放到總線上廣播出去&#xff0c;其他各個C…

(c++)string的模擬實現

目錄 1.構造函數 2.析構函數 3.擴容 1.reserve(擴容不初始化) 2.resize(擴容加初始化) 4.push_back 5.append 6. 運算符重載 1.一個字符 2.一個字符串 7 []運算符重載 8.find 1.找一個字符 2.找一個字符串 9.insert 1.插入一個字符 2.插入一個字符串 9.erase 10…

學習筆記(24): 機器學習之數據預處理Pandas和轉換成張量格式[2]

學習筆記(24): 機器學習之數據預處理Pandas和轉換成張量格式[2] 學習機器學習&#xff0c;需要學習如何預處理原始數據&#xff0c;這里用到pandas&#xff0c;將原始數據轉換為張量格式的數據。 學習筆記(23): 機器學習之數據預處理Pandas和轉換成張量格式[1]-CSDN博客 下面…

LeetCode 2297. 跳躍游戲 VIII(中等)

題目描述 給定一個長度為 n 的下標從 0 開始的整數數組 nums。初始位置為下標 0。當 i < j 時&#xff0c;你可以從下標 i 跳轉到下標 j: 對于在 i < k < j 范圍內的所有下標 k 有 nums[i] < nums[j] 和 nums[k] < nums[i] , 或者對于在 i < k < j 范圍…

【前端】緩存相關

本知識頁參考&#xff1a;https://zhuanlan.zhihu.com/p/586060532 1. 概述 1.1 應用場景 靜態資源 場景&#xff1a;圖片、CSS、JS 文件等靜態資源實現&#xff1a;使用 HTTP 緩存控制頭&#xff0c;或者利用 CDN 進行邊緣緩存 數據緩存 場景&#xff1a;請求的返回結果實現…

獵板硬金鍍層厚度:高頻通信領域的性能分水嶺

在 5G 基站、毫米波雷達等高頻場景中&#xff0c;硬金鍍層厚度的選擇直接決定了 PCB 的信號完整性與長期可靠性。獵板硬金工藝&#xff1a; 1.8μm 金層搭配羅杰斯 4350B 基材的解決方案&#xff0c;在 10GHz 頻段實現插入損耗&#xff1c;0.15dB/cm&#xff0c;較常規工藝降低…

第35次CCF計算機軟件能力認證-5-木板切割

原題鏈接&#xff1a; TUOJ 我自己寫的35分正確但嚴重超時的代碼 #include <bits/stdc.h> using namespace std; int main() {int n, m, k;cin >> n >> m >> k;vector<unordered_map<int, int>> mp(2);int y;for (int i 1; i < n; …

【藍橋杯】包子湊數

包子湊數 題目描述 小明幾乎每天早晨都會在一家包子鋪吃早餐。他發現這家包子鋪有 NN 種蒸籠&#xff0c;其中第 ii 種蒸籠恰好能放 AiAi? 個包子。每種蒸籠都有非常多籠&#xff0c;可以認為是無限籠。 每當有顧客想買 XX 個包子&#xff0c;賣包子的大叔就會迅速選出若干…

pikachu通關教程-目錄遍歷漏洞(../../)

目錄遍歷漏洞也可以叫做信息泄露漏洞、非授權文件包含漏洞等. 原理:目錄遍歷漏洞的原理比較簡單&#xff0c;就是程序在實現上沒有充分過濾用戶輸入的../之類的目錄跳轉符&#xff0c;導致惡意用戶可以通過提交目錄跳轉來遍歷服務器上的任意文件。 這里的目錄跳轉符可以是../…

[概率論基本概念4]什么是無偏估計

關鍵詞&#xff1a;Unbiased Estimation 一、說明 對于無偏和有偏估計&#xff0c;需要了解其敘事背景&#xff0c;是指整體和抽樣的關系&#xff0c;也就是說整體的敘事是從理論角度的&#xff0c;而估計器原理是從實踐角度說事&#xff1b;為了表明概率理論&#xff08;不可…

面試題——計算機網絡:HTTP和HTTPS的區別?

HTTP&#xff08;HyperText Transfer Protocol&#xff09;&#xff1a;作為互聯網上應用最廣泛的網絡通信協議&#xff0c;HTTP是基于TCP/IP協議族的應用層協議。它采用標準的請求-響應模式進行通信&#xff0c;通過簡潔的報文格式&#xff08;包含請求行、請求頭、請求體等&a…

uni-app學習筆記十九--pages.json全局樣式globalStyle設置

pages.json 頁面路由 pages.json 文件用來對 uni-app 進行全局配置&#xff0c;決定頁面文件的路徑、窗口樣式、原生的導航欄、底部的原生tabbar 等。 導航欄高度為 44px (不含狀態欄)&#xff0c;tabBar 高度為 50px (不含安全區)。 它類似微信小程序中app.json的頁面管理部…