您的位置:首页 > 其它

一个简单单点登录SSO的实现(.net到j2ee)

2014-05-15 21:26 567 查看
单点登录实现的方式有很多,这里介绍一种使用时间戳和md5加密的方式,实现了SSO集成端(由.net实现,在此称为系统A)到应用系统B的单点登录(由j2ee实现,在此称为系统B)。即登录了A系统,能通过A系统直接跳转到B系统。

其基本思路是:由系统A按照一定的规则构建带参数的请求连接,该连接包含三个参数:用户名auth_user, 时间戳auth_timestamp,以及由前两者进行加密而得来的签名auth_signature(本文采用了md5加密)。在系统B中,接收到访问请求后,解析时间戳,时间戳的有效时间决定了该访问链接是否合法,这也防止了有人直接复制链接访问系统。时间戳有效后,使用用户名和时间戳生成签名,并校验该签名是否和请求链接的auth_signature一致,如果一致则是合法的SSO请求。

该方法必须保持系统A/B的md5加密算法完全一致。

同时,该方法通过三方面保证了SSO安全性:1、时间戳有效性 2、签名的唯一性 3、md5加密后字符串处理可定制(A/B加密后字符串再次处理)

以下为具体实现步骤:

1、系统A(SSO集成端)的处理和md5加密

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebApplication1
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

}

protected void Button1_Click(object sender, EventArgs e)
{
string host = "localhost:8080";
string auth_user = "user_test";
string auth_timestamp = (DateTime.Now.Subtract(DateTime.Parse("1970-1-1")).TotalSeconds - 28800).ToString().Split('.')[0]; ;
string auth_signature = this.md5(auth_user + auth_timestamp).ToLower();
string url = String.Format("http://{0}/auth/loginSSO?auth_signature={1}&auth_timestamp={2}&auth_user={3}"
, host, auth_signature, auth_timestamp, auth_user).Replace("@", "%40");
this.Label1.Text = url;
Response.Redirect(url);

}

public String md5(String s)
{
System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(s);
bytes = md5.ComputeHash(bytes);
md5.Clear();
string ret = "";
for (int i = 0; i < bytes.Length; i++)
{
ret += Convert.ToString(bytes[i], 16).PadLeft(2, '0');
}
return ret.PadLeft(32, '0');
}

}
}


2、对应的系统B(J2EE应用端,使用了Spring MVC)的处理

/**
* 单点登录
* @param request
* @param auth_signature 签名
* @param auth_timestamp 时间戳
* @param auth_user 用户名
* @param model
* @return
*/
@RequestMapping("/loginSSO")
public String loginSystemBySSO(HttpServletRequest request,String auth_signature,String auth_timestamp,String auth_user,Model model){
//校验时间戳是否过期
long curTime=System.currentTimeMillis()/1000;
long abs=Math.abs(curTime-Long.parseLong(auth_timestamp));
if(abs>3){
model.addAttribute("errMsg", "时间戳过期!!!");
return "login";
}

HttpSession session = request.getSession();
SessionContainer sessionContainer = (SessionContainer) session.getAttribute("SessionContainer");
if (null == sessionContainer)
sessionContainer = new SessionContainer();
UserInfo user = null;
if (StrUtil.isEmpty(auth_user)) {
model.addAttribute("errMsg", "用户名不能为空!!!");
return "login";
} else {
DetachedCriteria criteria=DetachedCriteria.forClass(UserInfo.class);
criteria.add(Restrictions.eq("loginName",auth_user));
List<UserInfo> userlist=new ArrayList<UserInfo>();
userlist = (List<UserInfo>) userService.findByCriteria(criteria);
if(userlist.size()>0)
user=userlist.get(0);
}
if (user==null) {
model.addAttribute("errMsg", "用户名或密码错误!!!");
return LOGIN;
}
//md5加密校验合理性
String md5Sig=MD5Util.MD5Encrypt(auth_user+auth_timestamp);
if(!md5Sig.equals(auth_signature)){
model.addAttribute("errMsg", "登录失败,请联系管理员!!!");

}
//sessionContainer.setIsLoginByIDCard("1");
return authListAndSession(session, sessionContainer, model, user,"0");

}

对应的md5加密工具类MD5Util.java为:

package com.test.framework.utils;

import java.security.MessageDigest;
import java.util.Arrays;

public class MD5Util {

// 该方法将你输入的字符串,通过md5加密,返回一个加密後的字符串
public static String MD5Encrypt(String inStr) {
MessageDigest md = null;
String outStr = null;
try {

md = MessageDigest.getInstance("MD5"); // 可以选中其他的算法如SHA
byte[] digest = md.digest(inStr.getBytes("UTF-8"));
//返回的是byte[],要转化为String存储比较方便
outStr = bytetoString(digest);
} catch (Exception nsae) {
nsae.printStackTrace();
}
return outStr;
}

public static String bytetoString(byte[] digest) {
String str = "";
String tempStr = "";
for (int i = 0; i < digest.length; i++) {
tempStr = (Integer.toHexString(digest[i] & 0xff));
//System.out.println(padLeft(tempStr, 2,'0'));
str = str + padLeft(tempStr, 2,'0');
}
return padLeft(str,32,'0');
}

private static String padLeft(String input, int size, char symbol) {
while (input.length() < size) {
input = symbol + input;
}
return input;
}

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