azure web应用部署

Azure AD单点登录 (Azure AD SSO)

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 Java web application 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与Java Web应用程序集成在一起,并将其与现有的Identity Management系统同步。 我使用Active Directory联合身份验证服务ADFS2016。在此博客中,我将在三个部分中共享集成过程。

  1. How to register Java Application in Azure AD如何在Azure AD中注册Java应用程序
  2. How to implement ADAL Library in Java Application如何在Java应用程序中实现ADAL库
  3. ADFS Configuration for Single Sign-On SSO单点登录SSO的ADFS配置

如何在Azure AD中注册Java应用程序 (How to Register Java Application in Azure AD)

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访问令牌。

https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications

https://docs.microsoft.com/zh-cn/azure/active-directory/develop/active-directory-integrating-applications

如何在Java Web应用程序中实现ADAL库 (How to implement ADAL library in Java Web Application)

The process of implementing ADAL Library in Java Application is comprised of total six steps:

在Java应用程序中实现ADAL库的过程总共包括六个步骤:

  1. Add ADAL Library Dependencies添加ADAL库依赖关系
  2. Register ADALFilter and add context parameters in your web.xml (Informing the Java App about Azure App configuration)注册ADALFilter并在web.xml中添加上下文参数(向Java App通知Azure App配置)
  3. Create AdalFilter创建AdalFilter
  4. Create the secure controller创建安全控制器
  5. Create AuthHelper class创建AuthHelper类
  6. Create aad.jsp创建一个aad.jsp

将adal库依赖项添加到Java应用程序 (Add adal library dependencies to the java application)

<dependency><groupId>com.microsoft.azure</groupId><artifactId>adal4j</artifactId><version>1.1.1</version>
</dependency>
<dependency><groupId>com.nimbusds</groupId><artifactId>oauth2-oidc-sdk</artifactId><version>4.5</version>
</dependency>

注册ADALFilter并在web.xml中添加上下文参数 (Register ADALFilter and add context parameters in your web.xml)

<context-param><param-name>authority</param-name><param-value>https://login.windows.net/</param-value>
</context-param>
<context-param><param-name>tenant</param-name><param-value>YOUR_TENANT_NAME</param-value>
</context-param><filter><filter-name>AdalFilter</filter-name><filter-class>com.azilen.aad.AdalFilter</filter-class><init-param><param-name>client_id</param-name><param-value><YOUR-CLIENT-ID></param-value></init-param><init-param><param-name>secret_key</param-name><param-value><YOUR-SECRET-KEY></param-value></init-param>
</filter>
<filter-mapping><filter-name> AdalFilter </filter-name><url-pattern>/secure/*</url-pattern>
</filter-mapping>

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 (Create AdalFilter)

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 sessionif (!AuthHelper.isAuthenticated(httpRequest)) {if (AuthHelper.containsAuthenticationData(httpRequest)) {Map<String, String> params = new HashMap<String, String>();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 authenticatedhttpResponse.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<AuthenticationResult> 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<AuthenticationResult> 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<AuthenticationResult> 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");}}

创建安全控制器 (Create secure controller)

@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";
}
}

创建AuthHelper类 (Create AuthHelper class)

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) {Map<String, String[]> map = 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.jsp (Create aad.jsp)

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "https://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>AAD Secure Page</title>
</head>
<body><p>Welcome, ${user}</p><ul><li><a href="<%=request.getContextPath()%>/index.jsp">Go Home</a></li></ul>
</body>
</html>

Azure AD SSO Java Web应用程序测试 (Azure AD SSO Java Web Application Test)

Below images shows the Azure AD login page and the success page after successful authentication.

下图显示了身份验证成功后的Azure AD登录页面和成功页面。

GitHub Repository.GitHub Repository下载完整的项目。

单点登录(SSO)的ADFS配置 (ADFS Configuration for Single Sign-On (SSO))

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系统之间的同步的过程包括三个步骤:

  1. Add Relying Party Trust添加依赖方信任
  2. Add client-id添加客户端ID
  3. Perform the Authority command in PowerShell of ADFS server在ADFS服务器的PowerShell中执行Authority命令

添加依赖方信任 (Add Relying Party Trust)

  • On Welcome page select Claims Aware在“欢迎”页面上,选择“ 声明感知”
  • On Select Data Source select Enter data about the relying party manually在“选择数据源”上,选择“ 手动输入有关依赖方的数据”
  • Provide any Display Name提供任何显示名称
  • Configure Certificate add self-signed certificate配置证书添加自签名证书
  • Configure URL: Select either as per your ADFS protocol配置URL:根据您的ADFS协议选择
    • Select the Enable support for the WS-Federation Passive protocol check box. Under Relying party WS-Federation Passive protocol URL, type the URL for this relying party trust.选中“ 启用对WS-Federation Passive协议的支持”复选框。 在“依赖方WS-Federation被动协议URL”下,键入此依赖方信任的URL。
    • Select the Enable support for the SAML 2.0 WebSSO protocol check box. Under Relying party 2.0 SSO service URL, type the Security Assertion Markup Language (SAML) service endpoint URL for this relying party trust.选中“ 启用对SAML 2.0 WebSSO协议的支持”复选框。 在“依赖方2.0 SSO服务URL”下,为此依赖方信任键入安全性声明标记语言(SAML)服务终结点URL。
  • Configure Identifiers: Add your application URL in Relying Party Trust Identifier.配置标识符:在依赖方信任标识符中添加您的应用程序URL。
  • Choose Access Control Policy: Select Permit All (Select as per your environment)选择访问控制策略:选择全部允许 (根据您的环境选择)
  • Ready to Add Trust: Review this setting准备添加信任:查看此设置
  • Finish.完。

Reference: https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust

参考: https : //docs.microsoft.com/zh-CN/windows-server/identity/ad-fs/operations/create-a-relying-party-trust

使用以下命令添加客户端ID (Add client-id with following command)

Add-ADFSClient -Name "SampleApplication" -ClientId "<CLIENTID>" -RedirectUri @("REDIRECTURI") -Description "OAuth 2.0 client for our Test application"

Reference: https://docs.microsoft.com/en-us/powershell/module/adfs/add-adfsclient?view=win10-ps

参考: https : //docs.microsoft.com/zh-cn/powershell/module/adfs/add-adfsclient?view=win10-ps

在ADFS服务器的PowerShell中执行以下Authority命令 (Perform following Authority command in PowerShell of ADFS server)

Grant-ADFSApplicationPermission -ClientRoleIdentifier "<CLIENTID>" -ServerRoleIdentifier "<AUTHORITY>" -ScopeNames "allatclaims","openid"
AUTHORITY eg: https://login.windows.net/

结论 (Conclusion)

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 Azilen Technologies harnessing his remarkable expertise over Spring, Hibernate, Liferay and JSF.

关于作者
Vijay是一位充满活力的程序员,他在过去的五年中一直在学习技术。 他是Azilen Technologies的高级软件工程师, 充分利用了他在Spring , Hibernate ,Liferay和JSF方面的卓越专业知识。

翻译自: https://www.journaldev.com/21773/azure-ad-sso-java-adfs-sso

azure web应用部署

azure web应用部署_Java Web应用程序中的Azure AD SSO,ADFS SSO配置相关推荐

  1. java web应用开发_Java Web应用开发基础

    模块1 Java Web应用开发概述 1.1 Web基础知识 1.1.1 Web应用及其开发 1.1.2 动态网页 1.1.3 B/S结构 1.1.4 JSP简介 1.2 创建第一个Web项目 1.2 ...

  2. java web 许令波_Java Web——Web概述

    已经很久没有更新博客了,过年忙着吃喝玩乐,就怠惰了一小下下?幸好这学期新开的课程都比较有趣--Java Web和Android.至少对于我自己来说,既充满挑战,又富有趣味. --[1.Web概述]-- ...

  3. java web 监听器 例子_Java web技术应用---监听器

    监听器的定义 (专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生变化时,立即采取相应的行动) 定义:Servlet规范中定义的一种特殊的类,用于监听Servlet ...

  4. java web 线程数_Java Web应用调优线程池

    最简单的单线程 我们先从基础开始.无论使用哪种应用服务器或者框架(如Tomcat.Jetty等),他们都有类似的基础实现.Web服务的基础是套接字(socket),套接字负责监听端口,等待TCP连接, ...

  5. java web项目测试_java web项目怎么测试?

    慕仰1329654 java web项目测试用Web的测试工具,如HtmlUnit,JWebUnit等.main()方法就可以测试,在main方法中获得connection对象将他输出就可以了.如果正 ...

  6. java中打开文件怎么实现_Java如何在程序中打开文件?

    有时需要在java程序中打开一个文件.java.awt.Desktop可用于在java中打开文件.Desktop实现依赖于平台,因此首先,应该检查操作系统是否支持Desktop类.此类查找注册到当前平 ...

  7. java项目部署_Java Web 项目的部署步骤

    关于java web项目的部署有很多种,我就把最近使用的一种跟大家分享下: 项目部署的前期准备: 1.XXX.war file 2.Tomcat server 当以上两项都准备好后,我们就可以开始项目 ...

  8. java web结束线程_java – 即使在Websphere中停止应用程序后,线程仍会继续运行

    我有一个长期运行的线程,使用org. springframework.scheduling.commonj.WorkManagerTaskExecutor创建 使用 Spring并在Websphere ...

  9. java web 性能 监控工具_Java web应用性能监控工具jwebap

    性能测试中,我们经常希望一个平台能拦截.profile.分析性能数据,现实在一点点逼近.Jwebap:51Testing软件测试网v)?F?#|+{sI$^ 效果图http://www.jwebap. ...

最新文章

  1. Nature:要想真正研究宿主-肠道微生物的相互作用,必须将相对定量变成绝对定量...
  2. SAP Spartacus里的HTTPErrorInterceptor的单元测试设计原理
  3. clone-graph
  4. 计算机辅助审计的特点是,浅谈新环境下计算机辅助审计的特点和应用_1
  5. Java构造时成员初始化的陷阱
  6. 大家一起做训练 第一场 A Next Test
  7. (7)ISE14.7无用引脚设置上下拉或高阻态(FPGA不积跬步101)
  8. 关于精英版stm32从模板工程移植RTT Spi驱动打开后编译不过的处理办法
  9. php如何增加字段,php如何增加字段
  10. ShaderLab学习总结
  11. 一个流氓软件有哪些典型特征?
  12. 查oracle执行的sql,oracle查询正在执行的sql
  13. The First Python man in Github
  14. Linux下用dd命令测试硬盘的读写速度
  15. ups计算软件_一篇文章读懂UPS
  16. 全国哀悼日 网站灰黑色CSS滤镜代码
  17. python 三色球问题
  18. label mpchart 饼图_ECharts饼图属性设置
  19. 无模型预测控制(model-free predictive control)+ESO
  20. 微信小程序之兼容问题

热门文章

  1. Oracle学习笔记之五sp1,PL/SQL之BULK COLLECT
  2. [转载] Python中三种类型的引号(单引号、双引号、三引号)
  3. Spring MVC 中使用AOP 进行统一日志管理--XML配置实现
  4. 在tomcat下利用service.xml对项目进行映射部署
  5. java 之UDP编程
  6. Hibernate的学习详解(4)
  7. 互联网十几年 我们错失了哪些创业机会
  8. 数据结构上机实践第三周项目2 - 建设“顺序表”算法库
  9. mui获取css参数,Mui-获取时间-调用手机api
  10. Oracle中的within,oracle中within group的用法