文档章节

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

猪刚烈
 猪刚烈
发布于 2014/09/24 13:55
字数 860
阅读 162
收藏 1

      单点登录实现的方式有很多,这里介绍一种使用时间戳和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;
	}

}


 

 

  

本文转载自:http://blog.csdn.net/jrn1012/article/details/25915027

猪刚烈
粉丝 22
博文 708
码字总数 110
作品 1
海淀
程序员
私信 提问
单点登录解决方案 —— Smart SSO

前几天我把 CAS 稍微研究了一下,感觉这个东西还有有点意思的,所以打算把它集成到 Smart 框架中来,但又不想与 Smart 耦合地太紧,于是我单独做了一个项目,叫做 Smart SSO。 Smart SSO 实际...

黄勇
2014/02/13
14.3K
6
JEESZ分布式框架--单点登录集成方案(二)

修改sso1下的web.xml。添加如下代码: 5.修改sso2下的web.xml。添加如下代码: 6.编辑sso1,sso2 index.jsp页面,复制如下代码: sso1 index.jsp: 这个是www.sso1.com 你好我是sso1页面: <%= r...

明理萝
2018/07/17
15
0
基础图解之分布式服务部署请求流程

今天,深层次和群里同学讨论关于分布式系统问题 汇总如下: 单体应用,分布式部署:保存会话信息(spring-session) 客户端cookies + 服务端 redis = 用户信息 单机应用中,HttpSession是通过Servl...

莫库什勒
04/11
8
0
JAVA WEB快速入门之从编写一个JSP WEB网站了解JSP WEB网站的基本结构、调试、部署

一、使用eclipse初始化一个JSP WEB项目(即:动态WEB项目),步骤如下: 如上图示注意选择TOMCAT版本 如上图示勾选生成web.xml,当然如果不勾选也行,但后续如果有需要用到配置的地方就需要再单...

编程SHA
04/20
18
0
JForum论坛单点登录的几种实现方式 (CAS和Cookie)

JForum论坛单点登录的几种实现方式 (CAS和Cookie) 王保政 Email:baozhengw@netease.com 2007-8-4 一、用CAS实现Jforum的单点登录 (一)CAS客户端应用的web.xml配置 CAS和jforum的安装过程本文...

迷途d书童
2012/03/09
214
0

没有更多内容

加载失败,请刷新页面

加载更多

php7-internal 7 zval的操作

## 7.7 zval的操作 扩展中经常会用到各种类型的zval,PHP提供了很多宏用于不同类型zval的操作,尽管我们也可以自己操作zval,但这并不是一个好习惯,因为zval有很多其它用途的标识,如果自己...

冻结not
昨天
4
0
溢出\越界\泄漏

溢出:栈溢出是指函数中的局部变量造成的溢出,递归次数太多也会栈溢出 一是分配的大小超过栈的最大值,char a[99999999999999999]; 二是分配的大小没有超过最大值,但是接收的buff比新buff小...

SibylY
昨天
3
0
线性表-链式(c/c++实现)

在写数据的结构就是自己排兵布阵,根据客户的需求可增删功能,顺序与链式编程思想是一样的,两个比较只需要改变实现功能这一块。 线性表(链式)实现的三个步骤: 定义所需的功能(LinkList....

白客C
昨天
4
0
导览Linux系统文件系统类型

虽然对于普通用户来说可能并不明显,但在过去十年左右的时间里,Linux 文件系统已经发生了显著的变化,这使它们能够更好对抗损坏和性能问题。 如今大多数 Linux 系统使用名为 ext4 的文件系统...

老孟的Linux私房菜
昨天
4
0
Eureka重要对象简介

在进行分析EurekaClient和EurekaServer之间通信的源码之前,我们首先需要熟悉一下几个实体类 InstanceInfo 这个类代表着EurekaClient实例,客户端向服务端请求注册时就会携带着这个实例,这个...

Java学习录
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部