微软OA认证/ADFS认证 java 源码解析
依照項目的需要,客戶需要使用微軟的認證,仔細走了一遍官方的源碼,希望可以給后來人 指條路
1.先去微軟的官網下載java版本的源代碼
下載地址
上面的下載頁面 會有一套具體的申請賬號+配置流程 ,跟著做就可以了
把下載好的java工程應用,導入到Tomcat上面運行就ok.
這里說一下 具體的的代碼流程
先來個總體的感受,上圖 (圖片太大,點擊圖片看大圖,或者下載看)
這個就是大體的認證的過程
1.案例中,所有的http請求都要通過 過濾器
2.要完成一次認證,客戶端必須要2次訪問Tomcat
3.只要Tomcat內存中,有Session的key=principal,只要這個key=principal 對應的數值不過期(默認3600)
那么所有的請求中 就不會訪問 微軟的認證服務器
有了宏觀的感受,下面看看具體的代碼,其實微軟官方的這個代碼中,文件還是比較多的,但是更多的都是一些工具類,真正核心的就是2個文件 BasicFilter和AadController
一個是過濾器 過濾所有請求,一個是控制層處理token,這個控制層的地址一般就是回調地址
這兩個文件中,最最最 重要的是過濾器,過濾器一共有300多行代碼,太長了,其實核心的也就幾十行,更多的是封裝的獨立的函數 ,這個可以不管,下面上這幾十行 核心 代碼
* Copyright ? Microsoft Open Technologies, Inc.** All Rights Reserved** 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** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS* OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION* ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A* PARTICULAR PURPOSE, MERCHANTABILITY OR NON-INFRINGEMENT.** See the Apache License, Version 2.0 for the specific language* governing permissions and limitations under the License.******************************************************************************/ package com.microsoft.aad.adal4jsample;import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URLEncoder; import java.text.ParseException; import java.util.*; import java.util.concurrent.*;import javax.naming.ServiceUnavailableException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;import com.microsoft.aad.adal4j.AuthenticationContext; import com.microsoft.aad.adal4j.AuthenticationException; import com.microsoft.aad.adal4j.AuthenticationResult; import com.microsoft.aad.adal4j.ClientCredential; import com.nimbusds.jwt.JWTParser; import com.nimbusds.oauth2.sdk.AuthorizationCode; import com.nimbusds.openid.connect.sdk.AuthenticationErrorResponse; import com.nimbusds.openid.connect.sdk.AuthenticationResponse; import com.nimbusds.openid.connect.sdk.AuthenticationResponseParser; import com.nimbusds.openid.connect.sdk.AuthenticationSuccessResponse; import org.apache.commons.lang3.StringUtils;public class BasicFilter implements Filter {public static final String STATES = "states";public static final String STATE = "state";public static final Integer STATE_TTL = 3600;public static final String FAILED_TO_VALIDATE_MESSAGE = "Failed to validate data received from Authorization service - ";private String clientId = "";private String clientSecret = "";private String tenant = "";private String authority;public void destroy() {}public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {if (request instanceof HttpServletRequest) {HttpServletRequest httpRequest = (HttpServletRequest) request;HttpServletResponse httpResponse = (HttpServletResponse) response;try {String currentUri = httpRequest.getRequestURL().toString();String queryStr = httpRequest.getQueryString();String fullUrl = currentUri + (queryStr != null ? "?" + queryStr : "");// 下面if()中函數用于判斷Session中是否有key=principal,封裝成了函數,其實函數里面就一行代碼if (!AuthHelper.isAuthenticated(httpRequest)) { // 下面if()中函數用來判斷是否包含Code 信息 if (AuthHelper.containsAuthenticationData(httpRequest)) {//如果包含了,那么就要進行處理code-->token,并把token存到Session,key=principalprocessAuthenticationData(httpRequest, currentUri, fullUrl);} else {//如果不包含,那就跳轉到微軟的認證界面sendAuthRedirect(httpRequest, httpResponse);return;}}// 下面if()中函數用來判斷 Session中key=principal的token是否過期if (isAuthDataExpired(httpRequest)) {updateAuthDataUsingRefreshToken(httpRequest);}} catch (AuthenticationException authException) {//如果出錯, 移除Session,并跳轉微軟認證地址removePrincipalFromSession(httpRequest);sendAuthRedirect(httpRequest, httpResponse);return;} catch (Throwable exc) {httpResponse.setStatus(500);request.setAttribute("error", exc.getMessage());request.getRequestDispatcher("/error.jsp").forward(request, response);}}chain.doFilter(request, response);}過濾的核心就是上面的幾行代碼,只不過某些小功能也封裝成函數了,函數嵌套調用比較多,看了頭暈
下面就是
AadController
AadController 中的訪問的接口一般做為回調函數,里面主要是拿Token進行相應的處理的,官方的案例是根據accessToken去申請用戶信息然后返回給前臺的界面
代碼不是很長 就2個函數
package com.microsoft.aad.adal4jsample;import java.net.HttpURLConnection; import java.net.URL;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession;import org.json.JSONObject; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod;import com.microsoft.aad.adal4j.AuthenticationResult;@Controller @RequestMapping(value="/secure/aad" ) public class AadController {@RequestMapping( method = { RequestMethod.GET, RequestMethod.POST })public String getDirectoryObjects(ModelMap model, HttpServletRequest httpRequest,HttpServletResponse resp) {HttpSession session = httpRequest.getSession(); //從session中取出TokenAuthenticationResult result = (AuthenticationResult) session.getAttribute(AuthHelper.PRINCIPAL_SESSION_NAME);resp.setCharacterEncoding("utf-8");if (result == null) {model.addAttribute("error", new Exception("AuthenticationResult not found in session."));return "error";} else {String data;try {String tenant = session.getServletContext().getInitParameter("tenant");data = getUsernamesFromGraph(result, tenant);//把用戶信息放到model中model.addAttribute("tenant", tenant);model.addAttribute("user", data);model.addAttribute("userInfo", result.getUserInfo());} catch (Exception e) {model.addAttribute("error", e);return "error";}}//跳轉到前臺界面進行展示return "secure/aad";}//這個函數就是一個http請求,根據accessToken獲取用戶的信息.一共兩個參數,一個是包含accessToken的認證信 //息,一個是租戶,在申請微軟的控制面板中有這個值private String getUsernamesFromGraph( AuthenticationResult result, String tenant) throws Exception {String urlString="https://graph.chinacloudapi.cn/me?api-version=2013-04-05";URL url = new URL(urlString);HttpURLConnection conn = (HttpURLConnection) url.openConnection();// Set the appropriate header fields in the request header.conn.setRequestProperty("api-version", "2013-04-05");conn.setRequestProperty("Authorization", result.getAccessToken());conn.setRequestProperty("Accept", "application/json;odata=minimalmetadata");String goodRespStr = HttpClientHelper.getResponseStringFromConn(conn, true);// logger.info("goodRespStr ->" + goodRespStr);int responseCode = conn.getResponseCode();JSONObject response = HttpClientHelper.processGoodRespStr(responseCode, goodRespStr);JSONObject jsonUser;jsonUser=response.getJSONObject("responseMsg");StringBuilder builder = new StringBuilder();User user = new User();JSONHelper.convertJSONObjectToDirectoryObject(jsonUser, user);builder.append(user.getUserPrincipalName() + "<br/>");return builder.toString();}}然后在界面中 用戶就可以看到一些用戶信息了,這些就是大體的 微軟認證的 官方的 后臺java代碼解析,希望可以幫助后人少走彎路
總結
以上是生活随笔為你收集整理的微软OA认证/ADFS认证 java 源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Intel现有移动版CPU介绍和性能评价
- 下一篇: Intel笔记本CPU大全