您的位置:首页 > 其它

单点登录(SSO)的简单实现

2013-10-18 18:44 281 查看
最近了解到SSO,以前真心没有了解过,就查了一下,在企业中,或者大的网站都会用到这个技术。

1. 什么是SSO

英文全称:Single Sign On ,单点登录。

SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次主要的登录映射到其他应用中用于同一个用户的登录的机

制。它是目前比较流行的企业业务整合的解决方案之一。

目前的企业应用环境中,往往有很多的应用系统,如办公自动化(OA)系统,财务管理系统,档案管理系统,信息查询系统等等。这些应用系统服务于企业的信息

化建设,为企业带来了很好的效益。但是,用户在使用这些应用系统时,并不方便。用户每次使用系统,都必须输入用户名称和用户密码,进行身份验证;而且应用系统不同,用

户账号就不同,用户必须同时牢记多套用户名称和用户密码。特别是对于应用系统数目较多,用户数目也很多的企业,这个问题尤为突出。问题的原因并不是系统开发出现失误,

而是缺少整体规划,缺乏统一的用户登录平台,使用SSO技术可以解决以上这些问题。

总之,通俗点儿说,使用SSO,一次登录,可以使用所有的系统。

2. SSO的基本实现原理

从网上查资料,简单的画了个图,最简单的实现吧,使用了Cookie。



3. 简单实现

首先, 我们需要建3个项目 sso项目,sso_webdemo01业务项目和sso_webdemo02业务项目。

3个项目中好多代码都是重复的,这里就直接复制了

3.1 sso项目

SSOAction

简单的实现了验证操作,

package org.ygy.sso.action;

import java.io.IOException;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import lombok.Data;
import lombok.EqualsAndHashCode;

import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.interceptor.SessionAware;
import org.ygy.sso.entity.UserEntity;

import com.opensymphony.xwork2.ActionSupport;

@Data
@EqualsAndHashCode(callSuper=false)
public class SSOAction extends ActionSupport implements ServletResponseAware , SessionAware{

private static final long serialVersionUID = -1783731180470175728L;

private String appName;
private String sessionId;
private String sourceUrl;

private UserEntity user;
private HttpServletResponse response;
private Map<String , Object> session;

@Override
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}

@Override
public void setSession(Map<String, Object> session) {
this.session = session;
}

//跳转到登陆界面
public String login_input() {
//这里可以获取传递过来的参数,
//这里的话,需要很多的验证操作的,这里就省略了
System.out.println("appName->" + appName);
System.out.println("sourceUrl->" + sourceUrl);

session.put("sourceUrl" , sourceUrl);

return SUCCESS;
}

public String login() throws IOException {
//这里简单的输出用户登陆信息,不做处理
System.out.println(user.getName() + "-->" + user.getPassword());

String ticket = System.currentTimeMillis() + "";

//登录成功后,重定向到原应用
String url = (String) session.get("sourceUrl");

Cookie cookie = new Cookie("sso.ticket" , ticket);
cookie.setMaxAge(60*60*3);
//这里有一个Cookie跨域的问题,这里暂时使用setPath的方式解决一下。
cookie.setPath("/");

//重定向回,用户最原始请求界面
response.addCookie(cookie);
response.sendRedirect(url);

return NONE;
}

}

struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
<constant name="struts.i18n.encoding" value="utf-8"></constant>
<constant name="struts.multipart.maxSize" value="20971520"/>
<constant name="struts.devMode" value="true" />

<package name="p_sso" namespace="/" extends="json-default">

<action name="login_input" class="org.ygy.sso.action.SSOAction" method="login_input">
<result name="success">/login.jsp</result>
</action>

<action name="login" class="org.ygy.sso.action.SSOAction" method="login">
</action>
</package>

</struts>


3.2 sso_webdemo01项目

业务系统的话,这里用了一个拦截器,拦截请求:

1.用户访问业务系统

2.在拦截器中,获取Cookie,查找指定的Cookie是否存在

3.存在,就跳转到用户要访问的界面

4.不存在,则跳转到SSO验证系统,进行登陆验证

package org.ygy.demo01.action;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

public class LoginInterceptor implements Interceptor {

private static final long serialVersionUID = 2012849085577361846L;

public void destroy() {
// TODO Auto-generated method stub

}

public void init() {
// TODO Auto-generated method stub

}

public String intercept(ActionInvocation invocation) throws Exception {
HttpServletRequest request = ServletActionContext.getRequest();

String result = "success";

String ticket = null;	//登录标记
//1.验证是否登录:通过Cookie
//ps:现在是因为跨域的问题,无法解决
Cookie[] cookies = request.getCookies();
for(Cookie cookie : cookies) {
if(cookie.getName().equals("sso.ticket")) {
ticket = cookie.getValue();
System.out.println("ok-->" + ticket);
break;
}
}

if(ticket == null) {
//Cookie中没有用户登录信息,需要跳转去登录
String sourceUrl = request.getRequestURL().toString();

HttpServletResponse response = ServletActionContext.getResponse();
response.sendRedirect("http://localhost:8080/sso/login_input.action?appName=webdemo01&&sourceUrl=" + sourceUrl);
} else {
//已经有Ticket,可以去SSO系统获取登录信息

result = invocation.invoke();
}

return result;
}

}


package org.ygy.demo01.action;

import com.opensymphony.xwork2.ActionSupport;

public class Demo01Action extends ActionSupport {

private static final long serialVersionUID = 847600349062523237L;

public String hello() {
return SUCCESS;
}
}


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
<constant name="struts.i18n.encoding" value="utf-8"></constant>
<constant name="struts.multipart.maxSize" value="20971520"/>
<constant name="struts.devMode" value="true" />

<package name="p_webdemo01" namespace="/" extends="struts-default">
<interceptors>
<interceptor name="auth" class="org.ygy.demo01.action.LoginInterceptor"></interceptor>

<interceptor-stack name="base">
<interceptor-ref name="auth"></interceptor-ref>
<interceptor-ref name="basicStack"></interceptor-ref>
</interceptor-stack>
</interceptors>

<default-interceptor-ref name="base"></default-interceptor-ref>

<action name="hello" class="org.ygy.demo01.action.Demo01Action" method="hello">
<result name="success">hello.jsp</result>
</action>
</package>

</struts>


3.3 sso_webdemo02项目

这个和上面的业务系统1是一样的,可以简单的复制一下。

3.4 测试

1. 访问业务系统 http://localhost:8080/sso_webdemo01/hello.action


会跳转到sso系统去验证,显示的是登陆界面

2. 输入基本信息,登陆



3. 系统会在跳转到



就简单说道这里吧,这是最简单的实现,深入研究的话,就去网上查阅更多的资料吧。

注意: 上面关于Cookie的说明是不太对的,可以看一下这篇转载的博客:

cookie.setPath()的用法
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: