Oracle EBS SSO单点登陆实现方法

一、创建一个新的SSOLogin.jsp

        该单点登录的校验服务接口主要由乙方服务商提供,主要分为两步,第一步调用Token授权接口获取Token,然后根据获取的Token调用获取用户信息接口。

        Token授权接口(POST请求):https://iam.xxxxx-in.com/idp/oauth2/getToken

        获取用户信息接口(GET请求):https://iam.xxxxx-in.com/idp/oauth2/getUserInfo

POST:

 //HTTP请求
    public static String httpRequestIO(String requestUrl, String param) {
    InputStream inputStream = null;
    String result = "";
    PrintWriter out = null;
    try {
        URL url = new URL(requestUrl);
        HttpURLConnection httpUrlConn = 
            (HttpURLConnection)url.openConnection();
		if (httpUrlConn instanceof HttpsURLConnection) {
                ((HttpsURLConnection) httpUrlConn).setHostnameVerifier(new HostnameVerifier() {
                    public boolean verify(String hostname,
                                          SSLSession sslsession) {
                        return true;
                    }
                });
            }
        httpUrlConn.setRequestProperty("Content-Type", 
                                       "application/x-www-form-urlencoded");
        // 发送POST请求必须设置如下两行
        httpUrlConn.setDoOutput(true);
        httpUrlConn.setDoInput(true);
        httpUrlConn.setRequestMethod("POST");
        // 获取URLConnection对象对应的输出流
        out = new PrintWriter(httpUrlConn.getOutputStream());
        // 发送请求参数
        out.print(param);
        // flush输出流的缓冲
        out.flush();
        httpUrlConn.connect();
        // 获得返回的输入流  
        inputStream = httpUrlConn.getInputStream();
        int responseCode = httpUrlConn.getResponseCode();
        if (responseCode == httpUrlConn.HTTP_OK) {
            // 获得输入流,从服务器端获得数据
            inputStream = httpUrlConn.getInputStream();
            return (changeInputStream(inputStream, "utf-8"));
        }
    } catch (Exception e) {
		result = e.getMessage();
        e.printStackTrace();
    }
    return result;
    }

    GET:

/**
	  * 向指定URL发送GET方法的请求
	  *
	  * @param url
	  *   发送请求的URL
	  * @param param
	  *   请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
	  * @return URL 所代表远程资源的响应结果
	  */
	 public static String sendGet(String url, String param) {
	  String result = "";
	  BufferedReader in = null;
	  String step = "";
	  try {
	    step = "1";
	   String urlNameString = url + "?" + param;
	   URL realUrl = new URL(urlNameString);
	   // 打开和URL之间的连接
	    step = "2";
	   URLConnection connection = realUrl.openConnection();
	   // 设置通用的请求属性
	    step = "3";
	   connection.setRequestProperty("accept", "*/*");
	   connection.setRequestProperty("connection", "Keep-Alive");
	   connection.setRequestProperty("user-agent",
		 "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko");
		step = "4";
	   // 建立实际的连接
	   connection.connect();
	   step = "5";
	   // 获取所有响应头字段
	   Map<String, List<String>> map = connection.getHeaderFields();
	   // 遍历所有的响应头字段
	   for (String key : map.keySet()) {
		System.out.println(key + "--->" + map.get(key));
	   }
	   // 定义 BufferedReader输入流来读取URL的响应
	   in = new BufferedReader(new InputStreamReader(
		 connection.getInputStream()));
	   String line;
	   while ((line = in.readLine()) != null) {
		result += line;
	   }
	  } catch (Exception e) {
	   System.out.println("发送GET请求出现异常!" + step + e);
	   e.printStackTrace();
	  }
	  // 使用finally块来关闭输入流
	  finally {
	   try {
		if (in != null) {
		 in.close();
		}
	   } catch (Exception e2) {
		e2.printStackTrace();
	   }
	  }
	  return result;
	 }

调用代码(非完整代码): 

  <%
    try{
    String sessionId=request.getSession().getId();
  //1,getToken 获取授权接口
  String code = request.getParameter("code");
   response.getWriter().println("code=" + code);

    String getToken = httpRequestIO("https://iam.xxxxx-in.com/idp/oauth2/getToken","&client_id=erp&grant_type=authorization_code&code=" + code + "&client_secret=396aba8a638a411cb4b5f09ccff0c35e"); 
  response.getWriter().println("\n getToken=" + getToken);
  out.println(getToken.replace("{","").replace("}","").replace("\"","").replace("data:",""));
    String[] accesstoken = getToken.replace("{","").replace("}","").replace("\"","").replace("data:","").split(",");
  String access_token = "";
  
    for(int i=0; i < accesstoken.length; i++){
      //获取access_token
      if(accesstoken[i].startsWith("access_token")){
        access_token = accesstoken[i].replace("access_token:","");
        out.println(accesstoken[i].replace("access_token:",""));
      }
      response.getWriter().println("accesstoken["+i+"]=" + accesstoken[i]);
    }
    //2,getUserInfo 获取用户信息接口 
    String getUserInfo = sendGet("https://iam.xxxxx-in.com/idp/oauth2/getUserInfo","&client_id=erp&access_token=" + access_token);
    response.getWriter().println("\n getUserInfo=" + getUserInfo);
    //out.println(getUserInfo.replace("{","").replace("}","").replace("\"","").replace("data:",""));
    String[] splitstr = getUserInfo.replace("{","").replace("}","").replace("\"","").replace("data:","").split(",");

    //用户名
    String userName = "";
    for(int i=0; i < splitstr.length; i++){
      //获取用户名
      if(splitstr[i].startsWith("loginName")){
        userName = splitstr[i].replace("loginName:","");
        out.println(splitstr[i].replace("loginName:",""));
      }
      response.getWriter().println("splitstr["+i+"]=" + splitstr[i]);
    }  
  
    //已登录
    if(userName.length() > 0 ){
      String forwardUrl = "";
    
      WebAppsContext wctx = null;
      boolean alreadySet = false;
      String langCode = request.getParameter("langCode");
      String checkUserResult = "";
  if(Utils.isAppsContextAvailable()){
    wctx = Utils.getAppsContext();
    alreadySet = true;
  }else{
    wctx = Utils.getAppsContext();
  }
  if(langCode != null){
          wctx.setCurrLang(langCode);
       }else{
            wctx.setCurrLang(langCode);
            langCode="ZHS";
  }
      java.sql.Connection con = wctx.getJDBCConnection();
      
      //验证用户名
      String userNameArray[] = validateUserName(userName, con);
      if(userNameArray[0].equals("E")){
        throw new Exception(userNameArray[1]);
      }
      
      //获取密码
      String pwd[] = getPwd(userName, con);     
      if(pwd[0].equals("E")){
        response.getWriter().println("<pre>" + pwd[1]);
        throw new RuntimeException("Error "+pwd[1]);
      }
      UserPwd pUser = new UserPwd(userName,pwd[1]);
      forwardUrl = SessionMgr.createAppsSession(pUser, request, response);
      //验证用户信息               
      SessionManager sessionmanager = wctx.getSessionManager();
      oracle.apps.fnd.security.SessionManager.AuthStatusCode authstatuscode = sessionmanager.validateLogin(pUser); 
       if (authstatuscode.VALID == authstatuscode ) {
         checkUserResult  = "VALID";
       }  else if ( authstatuscode.INVALID == authstatuscode ){
         checkUserResult  = "INVALID";
       }  else if ( authstatuscode.EXPIRED == authstatuscode ){
         checkUserResult  = "EXPIRED";
       } 
      //wctx.releaseJDBCConnection();
      //跳转
      if (authstatuscode.toString().equals("EXPIRED")) {
          //response.sendRedirect("errorpage.jsp?em="+stringtoUnicode("此账户在")+"ERP"+stringtoUnicode("已过有效期,请联系系统管理员"));
          response.getWriter().println("此账户在ERP已过有效期,请联系系统管理员");

      }else if (authstatuscode.toString().equals("INVALID")) {
         //response.sendRedirect("errorpage.jsp?em="+stringtoUnicode("对不起,您没有")+"ERP"+stringtoUnicode("系统用户权限;如需申请ERP系统用户权限,请联系BP&IT申请"));
         response.getWriter().println("对不起,您没有系统用户权限;如需申请ERP系统用户权限,请联系BP&IT申请");
      }else {
         response.getWriter().println("<pre>" + "<br/>"+forwardUrl + "<br/>"+authstatuscode);
         response.sendRedirect(forwardUrl+"&client_id=erp&code=" + code +"&language_code=ZHS&lang_code=ZHS");
      }      
    }else{
      //登录失败跳转到SSO登录页面
    //String returnUrl= "http://ebsprod-ap1.xxxxx-in.com:8000";
      //returnUrl=URLEncoder.encode(returnUrl);
      //response.sendRedirect("https://iam.xxxxx-in.com/idp/profile/OAUTH2/Redirect/GLO?returnurl=" + returnUrl);
    //response.getWriter().println("登录失败");
    response.sendRedirect("https://iam.xxxxx-in.com/idp/themes/default/fail.html");
    }
    }catch(Exception e){
    response.getWriter().println("<pre>" + e.toString());
      e.printStackTrace();
      //显示错误信息,退出
      //response.setHeader("refresh", "3;url=https://iam.xxxxx-in.com/idp/themes/default/fail.html");
    response.sendRedirect("https://iam.xxxxx-in.com/idp/themes/default/fail.html");
      
    }
  %>

      

二、修改RF.jsp和OALogout.jsp

       JSP存放目录:$OAH_TOP/html,从目录下载RF.jsp和OALogout.jsp两个文件

      修改RF.jsp,将登陆网址改为默认跳转到新的SSOLogin.jsp

      找到这一段%><jsp:forward page="<%= url.substring(index + 9) %>" /><%

      修改为:

oracle.apps.fnd.common.WebAppsContext ctx = Utils.getAppsContext();;
          boolean chk = ctx.validateSession(oracle.apps.fnd.framework.webui.OAJSPHelper.getIcxCookie(request, false));
          if(!url.contains("sso")){
                %><jsp:forward page="<%= url.substring(index + 9) %>" /><%
          }else{
              String returnUrl= "http://ebsprod-ap1.xxxxx-in.com:8000/OA_HTML/SSOLogin.jsp";
              returnUrl=URLEncoder.encode(returnUrl);
          response.sendRedirect("https://iam.xxxx-in.com/idp/oauth2/authorize?redirect_uri="+returnUrl+ "&client_id=erp&response_type=code" );
          }

       

      修改OALogout.jsp,找到这一段response.sendRedirect(logoutUrl);

      修改为:

String returnUrl= "http://ebsprod-ap1.xxxxx-in.com:8000";
	returnUrl=URLEncoder.encode(returnUrl);
	response.sendRedirect("https://iam.xxxxx-in.com/idp/profile/OAUTH2/Redirect/GLO?redirctToUrl="+returnUrl);

上面分别修改登陆与登出的代码,URLEncoder方法需要引用<%@ page import="java.net.URLEncoder"%>

三、上传与编译

JSP上传路径:$OAH_TOP/html

编译路径:cd $FND_TOP/patch/115/bin

清除.class 
rm $COMMON_TOP/_pages/*SSOLogin*
rm $COMMON_TOP/_pages/_OALogout.class
rm $COMMON_TOP/_pages/_RF.class

编译:
$FND_TOP/patch/115/bin/ojspCompile.pl --compile -s OALogout.jsp
$FND_TOP/patch/115/bin/ojspCompile.pl --compile -s SSOLogin.jsp
$FND_TOP/patch/115/bin/ojspCompile.pl --compile -s RF.jsp

编译成功后查看:
$COMMON_TOP/_pages

最后重启服务:
adapcctl.sh stop
adapcctl.sh start

adoacorectl.sh stop
adoacorectl.sh start

该篇仅提供一种实现思路,感兴趣的朋友可参考。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值