本文共 15174 字,大约阅读时间需要 50 分钟。
azure web应用部署
The Single Sign-On feature is getting popular among developers to handle Application Access Management while developing multi-faced applications due to its remarkable advantages. Azure Active Directory is one of the most popular solutions used for Directory Management, Application Access Management and secured Identity Management, which offers the efficient Single Sign-On feature as well.
单点登录功能因其显着的优势而在开发多面应用程序的同时,在处理应用程序访问管理的开发人员中越来越受欢迎。 Azure Active Directory是用于目录管理,应用程序访问管理和安全的身份管理的最受欢迎的解决方案之一,该解决方案还提供了有效的单一登录功能。
Recently, I integrated Azure AD SSO with a along with synchronizing it with existing Identity Management system. I used Active Directory Federation Services ADFS 2016. In this blog, I am sharing the integration process in three sections.
最近,我将Azure AD SSO与集成在一起,并将其与现有的Identity Management系统同步。 我使用Active Directory联合身份验证服务ADFS2016。在此博客中,我将在三个部分中共享集成过程。
Follow the instructions given in the link below to register the Java Application with Azure AD using Active Directory Authentication Library for Java (ADAL4J) and to acquire JWT access token.
请按照下面的链接中给出的说明,使用Java Active Directory身份验证库(ADAL4J)向Azure AD注册Java应用程序,并获取JWT访问令牌。
The process of implementing ADAL Library in Java Application is comprised of total six steps:
在Java应用程序中实现ADAL库的过程总共包括六个步骤:
AdalFilter
创建AdalFilter
aad.jsp
创建一个aad.jsp
com.microsoft.azure adal4j 1.1.1 com.nimbusds oauth2-oidc-sdk 4.5
authority https://login.windows.net/ tenant YOUR_TENANT_NAME AdalFilter com.azilen.aad.AdalFilter client_id secret_key AdalFilter /secure/*
Replace values of following with actual that you got from Azure portal while registering your application as described in the previous step.
按照上一步中的说明,在注册应用程序时将以下值替换为从Azure门户获得的实际值。
YOUR-CLIENT-ID and YOUR-SECRET-KEY, authority (is your azure ad’s login page), YOUR_TENANT_NAME is the organization name.
YOUR-CLIENT-ID和YOUR-SECRET-KEY(授权)(是您的天蓝色广告的登录页面),YOUR_TENANT_NAME是组织名称。
AdalFilter checks if current session has valid PRINCIPAL_SESSION_NAME
stored, if not then it will redirect to Azure login page (Authority).
AdalFilter将检查当前会话是否存储了有效的PRINCIPAL_SESSION_NAME
,否则将重定向到Azure登录页面(Authority)。
public class AdalFilter implements Filter { 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 = request.getScheme() + "://" + request.getServerName() + ("http".equals(request.getScheme()) && request.getServerPort() == 80 || "https".equals(request.getScheme()) && request.getServerPort() == 443 ? "" : ":" + request.getServerPort()) + httpRequest.getRequestURI(); String fullUrl = currentUri + (httpRequest.getQueryString() != null ? "?" + httpRequest.getQueryString() : ""); // check if user has a session if (!AuthHelper.isAuthenticated(httpRequest)) { if (AuthHelper.containsAuthenticationData(httpRequest)) { Mapparams = new HashMap (); for (String key : request.getParameterMap().keySet()) { params.put(key, request.getParameterMap().get(key)[0]); } AuthenticationResponse authResponse = AuthenticationResponseParser.parse(new URI(fullUrl), params); if (AuthHelper.isAuthenticationSuccessful(authResponse)) { AuthenticationSuccessResponse oidcResponse = (AuthenticationSuccessResponse) authResponse; AuthenticationResult result = getAccessToken(oidcResponse.getAuthorizationCode(), currentUri); createSessionPrincipal(httpRequest, result); } else { AuthenticationErrorResponse oidcResponse = (AuthenticationErrorResponse) authResponse; throw new Exception(String.format("Request for auth code failed: %s - %s", oidcResponse.getErrorObject().getCode(), oidcResponse.getErrorObject().getDescription())); } } else { // not authenticated httpResponse.setStatus(302); httpResponse.sendRedirect(getRedirectUrl(currentUri)); return; } } else { // if authenticated, how to check for valid session? AuthenticationResult result = AuthHelper.getAuthSessionObject(httpRequest); if (httpRequest.getParameter("refresh") != null) { result = getAccessTokenFromRefreshToken(result.getRefreshToken(), currentUri); } else { if (httpRequest.getParameter("cc") != null) { result = getAccessTokenFromClientCredentials(); } else { if (result.getExpiresOnDate().before(new Date())) { result = getAccessTokenFromRefreshToken(result.getRefreshToken(), currentUri); } } } createSessionPrincipal(httpRequest, result); } } catch (Throwable exc) { httpResponse.setStatus(500); request.setAttribute("error", exc.getMessage()); httpResponse.sendRedirect(((HttpServletRequest) request).getContextPath() + "/error.jsp"); } } chain.doFilter(request, response); } private AuthenticationResult getAccessTokenFromClientCredentials() throws Throwable { AuthenticationContext context = null; AuthenticationResult result = null; ExecutorService service = null; try { service = Executors.newFixedThreadPool(1); context = new AuthenticationContext(authority + tenant + "/", true, service); Future future = context.acquireToken("https://graph.windows.net", new ClientCredential(clientId, clientSecret), null); result = future.get(); } catch (ExecutionException e) { throw e.getCause(); } finally { service.shutdown(); } if (result == null) { throw new ServiceUnavailableException("authentication result was null"); } return result; } private AuthenticationResult getAccessTokenFromRefreshToken(String refreshToken, String currentUri) throws Throwable { AuthenticationContext context = null; AuthenticationResult result = null; ExecutorService service = null; try { service = Executors.newFixedThreadPool(1); context = new AuthenticationContext(authority + tenant + "/", true, service); Future future = context.acquireTokenByRefreshToken(refreshToken, new ClientCredential(clientId, clientSecret), null, null); result = future.get(); } catch (ExecutionException e) { throw e.getCause(); } finally { service.shutdown(); } if (result == null) { throw new ServiceUnavailableException("authentication result was null"); } return result; } private AuthenticationResult getAccessToken(AuthorizationCode authorizationCode, String currentUri) throws Throwable { String authCode = authorizationCode.getValue(); ClientCredential credential = new ClientCredential(clientId, clientSecret); AuthenticationContext context = null; AuthenticationResult result = null; ExecutorService service = null; try { service = Executors.newFixedThreadPool(1); context = new AuthenticationContext(authority + tenant + "/", true, service); Future future = context.acquireTokenByAuthorizationCode(authCode, new URI(currentUri), credential, null); result = future.get(); } catch (ExecutionException e) { throw e.getCause(); } finally { service.shutdown(); } if (result == null) { throw new ServiceUnavailableException("authentication result was null"); } return result; } private void createSessionPrincipal(HttpServletRequest httpRequest, AuthenticationResult result) throws Exception { httpRequest.getSession().setAttribute(AuthHelper.PRINCIPAL_SESSION_NAME, result); } private String getRedirectUrl(String currentUri) throws UnsupportedEncodingException { String redirectUrl = authority + this.tenant + "/oauth2/authorize?response_type=code%20id_token&scope=openid&response_mode=form_post&redirect_uri=" + URLEncoder.encode(currentUri, "UTF-8") + "&client_id=" + clientId + "&resource=https%3a%2f%2fgraph.windows.net" + "&nonce=" + UUID.randomUUID() + "&site_id=500879"; return redirectUrl; } public void init(FilterConfig config) throws ServletException { clientId = config.getInitParameter("client_id"); authority = config.getServletContext().getInitParameter("authority"); tenant = config.getServletContext().getInitParameter("tenant"); clientSecret = config.getInitParameter("secret_key"); }}
@Controller@RequestMapping("/secure/aad")public class AadController { @RequestMapping(method = { RequestMethod.GET, RequestMethod.POST })public String getDirectoryObjects(ModelMap model, HttpServletRequest httpRequest) { HttpSession session = httpRequest.getSession(); log.info("session: " + session); AuthenticationResult result = (AuthenticationResult) session.getAttribute(AuthHelper.PRINCIPAL_SESSION_NAME); if (result == null) { model.addAttribute("error", new Exception("AuthenticationResult not found in session.")); return "/error"; } else { try { log.info("JWT token details:-"); JWT jwt = JWTParser.parse(result.getIdToken()); for (String key : jwt.getJWTClaimsSet().getAllClaims().keySet()) { log.info(key + ":" + jwt.getJWTClaimsSet().getAllClaims().get(key)); } model.addAttribute("user", jwt.getJWTClaimsSet().getStringClaim("unique_name")); } catch (ParseException e) { log.error("Exception:", e); } } return "/secure/aad";}}
public final class AuthHelper { public static final String PRINCIPAL_SESSION_NAME = "principal"; private AuthHelper() { } public static boolean isAuthenticated(HttpServletRequest request) { return request.getSession().getAttribute(PRINCIPAL_SESSION_NAME) != null; } public static AuthenticationResult getAuthSessionObject(HttpServletRequest request) { return (AuthenticationResult) request.getSession().getAttribute(PRINCIPAL_SESSION_NAME); } public static boolean containsAuthenticationData(HttpServletRequest httpRequest) { Mapmap = httpRequest.getParameterMap(); return (httpRequest.getMethod().equalsIgnoreCase("POST") || httpRequest.getMethod().equalsIgnoreCase("GET")) && (httpRequest.getParameterMap().containsKey(AuthParameterNames.ERROR) || httpRequest.getParameterMap().containsKey(AuthParameterNames.ID_TOKEN) || httpRequest.getParameterMap().containsKey(AuthParameterNames.CODE)); } public static boolean isAuthenticationSuccessful(AuthenticationResponse authResponse) { return authResponse instanceof AuthenticationSuccessResponse; }}
AAD Secure Page Welcome, ${user}
Below images shows the Azure AD login page and the success page after successful authentication.
下图显示了身份验证成功后的Azure AD登录页面和成功页面。
To configure ADFS 2016, first please make sure that the application is running on SSL. The process of configuring ADFS to enable the synchronization between Azure AD and existing Identity Management system is comprised of three steps:
要配置ADFS 2016,首先请确保该应用程序在SSL上运行。 配置ADFS以启用Azure AD与现有Identity Management系统之间的同步的过程包括三个步骤:
Reference:
参考: :
Add-ADFSClient -Name "SampleApplication" -ClientId "" -RedirectUri @("REDIRECTURI") -Description "OAuth 2.0 client for our Test application"
Reference:
参考: :
Grant-ADFSApplicationPermission -ClientRoleIdentifier "" -ServerRoleIdentifier " " -ScopeNames "allatclaims","openid"AUTHORITY eg: https://login.windows.net/
Regardless of the size and nature of any application, developers can deliver centralized policy-based access control to the application by utilizing Azure Active Directory’s standard platform. This integration and synchronization experience uplifted my knowledge of addressing business needs while simplifying the user journey across the system.
无论任何应用程序的大小和性质如何,开发人员都可以通过利用Azure Active Directory的标准平台为应用程序提供基于策略的集中式访问控制。 这种集成和同步的经验丰富了我在解决业务需求方面的知识,同时简化了用户跨系统的旅程。
About Author
Vijay is a vigorous programmer who breathes technology for last five years. He is Sr. Software Engineer at harnessing his remarkable expertise over , , Liferay and JSF.关于作者
Vijay是一位充满活力的程序员,他在过去的五年中一直在学习技术。 他是高级软件工程师, 利用了他在 , ,Liferay和JSF方面的卓越专业知识。翻译自:
azure web应用部署
转载地址:http://syqzd.baihongyu.com/