大家好,今天给大家分享一下实际项目中的单点登录开发。
背景:通常情况下,每个公司都有自己的单点登录规则,最简单的情况为验证当前登录的用户(人员的登录名、或者用户编码),是否为目标项目的真实人员。用传递过来的登录名或者用户编码进行效验,是否为合法用户,在网络传输过程中,需要对信息进行加密,在开发过程中需要考虑进去。本次分享为不加密的情况,方便讲解!
1.先看看效果,单点登录需要源网站和目标网站对应的服务都启动,下图为源网络首页,在登录后,正常情况下进行目标网站主页面,用户名异常的情况或者目标网站服务没有启动的情况下,会给出提示!
源网站首页
下图为—目标服务没有启动,或者对应的代码逻辑在服务器上没有发布。看到此提示(项目自己输出的日志记录,一个好的开发习惯需要对日志进行细化,方便遇到问题时,及时给出解决方案。)
异常输出,目标网站无法访问
正常登录后,见下图—目标网站的主页面
目标网站主页面–登录后的首页
如果页面不需要登录到主页面,可根据业务,调整目标页面,如下图,调整到移动端首页
调整参数,调整到其他子页面中
谷歌浏览器可调整显示终端,下图为浏览器的移动端展示,鼠标右键–检查–点击下图中的图片即可
移动端调试截图
移动端待办列表首页
移动端待办列表首页
2.源代码分享,源网站就是一个简单的servlet提交,servlet项目创建可参见我之前的分享,代码结构见截图
源网站–java web项目
LoginServlet.java 源码见下图
package com.test;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/LoginServlet")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
Map<String, String> tokenInfo = new HashMap<String, String>();
String type=request.getParameter("type");
String url="#34;;
String userName = request.getParameter("userN");
String thirdurl = "";
String ticket = UUID.randomUUID().toString();
String name=request.getParameter("name");
tokenInfo.put(name,ticket);
if("token_M3_pend".equals(type)){
thirdurl = "/seeyon/m3/apps/m3/todo/layout/todo-list.html";
}
url+="&type="+type+"&userName="+userName+"&ticket="+ticket+"&thirdurl="+thirdurl;
response.sendRedirect(url);
}
}
目标网站单点登录,基于我公司的插件开发,我们只需要建一个单点登录的握手类,此类用于接收传过来的参数跳转。
pluginCfg.xml—-自定义插件的唯一标识, 此开发是基于我们公司的开发规范,新增的代码不能影响以往其他业务。实际情况,开发需要参照自己公司的单点登录规范进行编码!!
SSOLoginContext.xml—握手类配置定义,属性name非常重要,是调整要使用的握手插件名
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "#34;>
<beans default-autowire="byName">
<bean id="appsso" class="com.seeyon.ctp.portal.sso.SSOLoginContext">
<property name="name" value="mySSO"/>
<property name="forward" value="true"/>
<property name="handshake">
<!-- 使用自己的握手实现 -->
<bean class="com.seeyon.apps.mySSO.MySSOLoginHandshake" />
</property>
</bean>
</beans>
目标网站,单点登录插件,源码截图
MySSOLoginHandshake 为单点登录需要实现自己业务的握手类,源码见下:
package com.seeyon.apps.mySSO;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.exceptions.BusinessException;
import com.seeyon.ctp.organization.bo.V3xOrgMember;
import com.seeyon.ctp.organization.manager.OrgManager;
import com.seeyon.ctp.portal.sso.SSOLoginContext;
import com.seeyon.ctp.portal.sso.SSOLoginHandshakeAbstract;
import com.seeyon.ctp.util.HttpClientUtil;
import sun.misc.BASE64Decoder;
public class MySSOLoginHandshake extends SSOLoginHandshakeAbstract{
private static final Log logger = LogFactory.getLog(MySSOLoginHandshake.class);
private OrgManager orgManager;
public void setOrgManager(OrgManager orgManager) {
this.orgManager = orgManager;
}
@Override
public String handshake(String ticket) {
String type=AppContext.getRawRequest().getParameter("type");
System.out.println(type);
if(ticket==null || ticket.equals("")){
return null;
}
try {
String userName=AppContext.getRawRequest().getParameter("userName");
V3xOrgMember member = orgManager.getMemberByMemberCode(userName);
if(member!=null){
return member.getLoginName();
}else{
logger.error("单点登录通过ticket:" + ticket +"查询人员为空");
}
} catch (BusinessException e) {
logger.error("--tqt--单点登录时,根据用户编号获取人员信息异常!", e);
}
return null;
}
@Override
public void logoutNotify(String curUser) {
//通过HttpClientUtil发送请求
HttpClientUtil u = new HttpClientUtil();
String LoginNameUrl="#34;+curUser;
//获取登录名
u.getContent(LoginNameUrl).toString();
}
@SuppressWarnings({ "unused", "restriction" })
private String decodeStr(String in) {
byte[] b = null;
String result = "";
if (in != null) {
BASE64Decoder decoder = new BASE64Decoder();
try {
b = decoder.decodeBuffer(in);
result = new String(b, "utf-8");
} catch (Exception e) {
}
}
return result;
}
@Override
public String getToUrl(HttpServletRequest req, SSOLoginContext ssoLoginContext, String ticket) {
return req.getParameter("thirdurl");
}
}