1. 概述
1.1 问题描述
OA 系统与 BI 系统集成,将 BI 绑定在 OA 系统的节点上,对于 OA 系统中想实现对 FineBI 的单点登录,用户需要在 OA 的登录界面中将用户名和密码传入到 BI 的认证地址进行认证。
若 OA 系统和 BI 系统不是部署在同一台服务器上,在登录时进行跨域,那么要如何通过 Ajax 实现 OA 系统和 BI 系统的跨域登录呢?
1.2 解决思路
iframe 方式和 Ajax 方式两种登录方式均可实现单点登录的跨域,但 Ajax 可以实现异步的单点登录,并且可对 BI 系统验证的结果进行处理,如登录超时;但是 iframe 不可以异步处理,并且在进行验证的时候,无法对验证的结果进行处理。
Ajax 登录方式天然支持跨域,故在 OA 系统的登录界面中直接通过 Ajax 将用户名密码发送到 BI 服务器进行后台验证,则可解决跨域单点登录问题。
2. 示例
启动两个工程,端口号分别为 37799 和 8080,将新建 HTML 文件 ajaxlogin.html、ajaxlogout.html 放到端口号为 37799 的工程下。访问http://localhost:37799/webroot/ajaxlogin.html,输入 8080 工程的用户名和密码,成功访问 8080 工程。
在登录成功的浏览器上新开标签页,访问http://localhost:37799/webroot/ajaxlogout.html,点击「登出」按钮,刷新之前登录成功的 8080 工程页面,用户被踢出登录。
注:本章示例适用于 PC 端。
2.1 环境准备
1)本文示例准备的两个工程分别为:
注:这两个工程需要有相同的用户名和密码。
本地工程,端口号为 37799
部署到 Tomcat 上的工程,端口号为 8080
Tomcat 服务器部署请参见:Tomcat服务器部署
2)启动两个工程。
2.2 新建登录页面
注1:根据实际情况修改代码中的访问路径或端口号。
注2:内网环境中,下面代码引用的 jquery.min.js 文件无法生效,需下载 JS 文件到本地并修改对应的路径,具体步骤请参见:单点登录常见问题。
2.2.1 用户名或密码中无特殊字符
新建 HTML 文件,命名为「ajaxlogin.html」,代码如下所示:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; " charset="UTF-8">
<script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
function doSubmit() {
var username = document.getElementById("username").value.trim();
var password = document.getElementById("password").value.trim();
if (username === "") {
window.alert("请输入用户名");
return false;
}
if (password === "") {
window.alert("请输入密码");
return false;
}
var url = "http://localhost:8080/webroot/decision/login/cross/domain" + "?fine_username=" + username + "&fine_password=" + password + "&validity=" + -1;
alert(url);
jQuery.ajax({
url: url,//单点登录的管理平台报表服务器
timeout: 5000,//超时时间(单位:毫秒)
dataType:"jsonp",//跨域采用jsonp方式
jsonp:"callback",
success: function (res) {
console.log(res);
if (res.errorCode) {
window.alert(res.errorMsg);
}else {
// 保存token并跳转到对应链接
window.location.href = "http://localhost:8080/webroot/decision";
}
},
error: function () {
alert("超时或服务器其他错误");// 登录失败(超时或服务器其他错误)
}
});
}
</script>
</head>
<body>
<p>请登录</p>
<form id="login" name="login" method="POST" action="">
<p>用户名:<input id="username" type="text" name="username"/></p>
<p>密 码:<input id="password" type="password" name="password"/></p>
<input type="button" value="登录" onClick="doSubmit()"/>
</form>
</body>
</html>
2.2.2 用户名或密码中有特殊字符
用户名或密码中有特殊字符,例如含有「&#」时,需对用户名或密码进行转码,本节提供两种转码方法:
1)方案一:使用encodeURIComponent()进行转码
var url = "http://localhost:8080/webroot/decision/login/cross/domain" + "?fine_username=" +encodeURIComponent(username)
+ "&fine_password=" + encodeURIComponent(password) + "&validity=" + -1;
HTML 代码示例:方案一.html
2)方案二:使用 data 传参
data:{"fine_username":username,"fine_password":password,validity:-1},
HTML 代码示例:方案二.html
2.3 注销用户页面
新建 HTML 文件,命名为「ajaxlogout.html」,代码如下所示:
注:根据实际情况修改代码中的访问路径或端口号。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; " charset="UTF-8">
<script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
function doSubmit() {
jQuery.ajax({
url:"http://localhost:8080/webroot/decision/logout/cross/domain",//单点登录的报表服务器
dataType:"jsonp",//跨域采用jsonp方式
jsonp:"callback",
timeout:5000,//超时时间(单位:毫秒)
success:function(data) {
if (data.status === "success") {
//登出成功
alert("已登出");
}
},
error:function(){
// 登出失败(超时或服务器其他错误)
}
});
}
</script>
</head>
<body>
<p>请登出</p>
<form id="login" name="login" method="POST" action="" >
<input type="button" value="登出" onClick="doSubmit()" />
</form>
</body>
</html>
2.4 将 HTML 文件放到指定位置
将保存后的 ajaxlogin.html、ajaxlogout.html 文件放到端口号为 37799 工程的%BI_HOME%/webapps/webroot文件夹下,如下图所示:
2.5 关闭安全防护相关按钮
1)以管理员身份进入端口号为 37799 工程的平台,点击「管理系统>安全管理」,关闭「内容嗅探攻击防护」、「点击劫持攻击防护」,如下图所示:
2)相同步骤关闭端口号为 8080 工程的「内容嗅探攻击防护」、「点击劫持攻击防护」。
2.6 效果查看
1)打开浏览器,访问:http://localhost:37799/webroot/ajaxlogin.html,输入端口号为 8080 工程的账号和密码,成功访问 8080 工程。如下图所示:
2)在登录成功的浏览器上新开标签页,访问http://localhost:37799/webroot/ajaxlogout.html,点击「登出」按钮,切换到之前登录成功的 8080 工程页面,刷新该页面,用户被踢出登录。如下图所示:
注:如果端口号为 37799 和端口号为 8080 的两个工程都开启 短信登录验证 ,访问http://localhost:37799/webroot/ajaxlogin.html时,ajax 单点登录会跳过短信验证直接登录成功。