SSO单点登录,简单模拟

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shuaipu813/article/details/53259292

SSO单点登录(以下全是个人理解,如果有误,共同批评进步)

1.什么是单点登录:

在不同的应用中,受保护的同一用户,登录一次就可以访问相关的其他系统应用。比如搜狐登录后,可以直接访问博客、邮箱等等,而不用再重新登录博客系统、邮箱系统等等。方便了用户的操作。

2.同域下单点登录实现:

单点登录流程和大概思路如下:


  我们用具体代码来实现以下操作:

我们有四个项目,app1、app2、ssofilter、ssoserver分别是web系统1、web系统2、拦截请求系统、sso认证中心。

app1系统结构如下:


就一个jsp文件,用来获取用户信息。app2系统的页面也一样。

我们先写sso认证中心的代码,这里只写主要的代码:

登录的代码,登录成功后写入cookie,将令牌和用户信息存入全局信息中

	/**
	 * get请求,表示没有登录直接访问。获取路径,返回登录页面
	 */
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//获取请求路径
		String backurl=request.getParameter("backurl");
		request.setAttribute("backurl", backurl);
		request.getRequestDispatcher("index.jsp").forward(request, response);
	}
	
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//解决中文乱码
		request.setCharacterEncoding("utf-8");
		String username=request.getParameter("username");
		String password=request.getParameter("password");
		String backurl=request.getParameter("backurl");
		try {
			User user=new User();
			//根据用户名名称查询用户
			user = UserUtil.getUserByname(username);
			if(null!=user&& password.equals(user.getPassword())){
				System.out.println("登录成功!");
				/*String[] uuid=UUID.randomUUID().toString().split("-");
				StringBuffer token=new StringBuffer();
				for (String string : uuid) {
					token.append(string);
				}*/
				//生成令牌,根据java生成uuid,将其中的-符号替换为空字符串,然后转成小写字母
				String token=UUID.randomUUID().toString().replace("-", "").toLowerCase();
				//根据自定义的全局工具类,将令牌作为key,将用户信息作为value存入Map中
				MapUtil.addToken(token, user);
				//创建一个cookie
				Cookie cookie=new Cookie("token", token);
				cookie.setHttpOnly(true);
				cookie.setPath("/");
				//将cookie添入响应中,返回客户端
				response.addCookie(cookie);
				if(StringUtils.isNullOrEmpty(backurl)){
					//如果没有获取到请求路径,表示用户直接访问login登录页面,这里可以将值设置为登录成功后的主页
					backurl="success";
				}else{
					//将路径解码
					backurl=URLDecoder.decode(backurl,"utf-8");
				}
				//重新定向到返回路径
				//response.sendRedirect(backurl);
				response.getWriter().println(backurl);
			}else{
				response.setContentType("text/html;utf-8");
				response.setCharacterEncoding("utf-8");
				System.out.println("用户名或密码不对!");
				response.getWriter().println("用户名或密码不对");
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
SSO认证中心,验证代码:
		//获取请求令牌
		String token=request.getParameter("token");
		//根据令牌去请求对应的用户信息
		User user=MapUtil.getUserByToken(token);
		//判断令牌是否有效
		if(null!=user){
			//有效,返回用户信息
			response.getWriter().println("username="+URLEncoder.encode(user.getUsername(),"utf-8")+";password="+user.getPassword());
		}else{
			//无效,返回空字符串
			response.getWriter().println("");
		}
拦截请求系统代码:
		//将ServletRequest和ServletResponse转为Http请求的
		HttpServletRequest httprequest=(HttpServletRequest)request;
		HttpServletResponse httpresponse=(HttpServletResponse)response;
		//获取cookie数组
		Cookie[] cookies=httprequest.getCookies();
		String token=null;
		if(null!=cookies && 0<cookies.length){
			for (Cookie cookie : cookies) {
				if(cookie.getName().equals("token")){
					token=cookie.getValue();
				}
			}
		}
		//获取url路径,?之前
		String url=httprequest.getRequestURI();
		//获取?之后的路径
		String queryurl=httprequest.getQueryString();
		if(null!=queryurl){
			url+="?"+queryurl;
		}
		if(null==token){
			//令牌为空,直接返回登录页面,重新登录生成
			httpresponse.sendRedirect(SSOLOGINURL+"?backurl="+URLEncoder.encode(url,"utf-8"));
		}else{
			//请求SSO服务端,验证令牌的有效性
			URL urlconn=new URL(SSOVAILDATE+"?token="+token);
			HttpURLConnection connection=(HttpURLConnection)urlconn.openConnection();
			connection.setRequestMethod("GET");  
			connection.setRequestProperty("Charset", "utf-8");
			connection.connect();
			InputStream input=connection.getInputStream();
			byte[] by=new byte[1024];
			input.read(by);
			String stringbuffer=new String(by);
			if(stringbuffer.length()>0){
				String[] userdata=stringbuffer.split(";");
				User user=new User();
				for (String string : userdata) {
					String[] string2=string.split("=");
						switch (string2[0]){
						case "username":
							user.setUsername(URLDecoder.decode(string2[1],"utf-8"));
							break;
						case "password":
							user.setPassword(string2[1]);
							break;
						}
					}
					request.setAttribute("user", user);
					filter.doFilter(httprequest, httpresponse);
				}else{
					//标示token无效,将请求定向到登录地址
					httpresponse.sendRedirect(SSOLOGINURL+"?backurl="+URLEncoder.encode(url,"utf-8"));
				}
			}
拦截请求系统打成jar包,加入web1和web2中使用,在web1和web2中配置拦截器
  <filter>
  	<filter-name>loginfilter</filter-name>
  	<filter-class>com.client.ssoFilter</filter-class>
  </filter>
  <filter-mapping>
  	<filter-name>loginfilter</filter-name>
  	<url-pattern>*.jsp</url-pattern>
  </filter-mapping>

还有SSO认证中心的登录页面:

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>   
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>登录</title>
<script type="text/javascript">
function submitData(){
	var httpRequest=createXMLHttpRequest();
	httpRequest.onreadystatechange=function(){
		if(httpRequest.readyState==4 && httpRequest.status==200){
			if("用户名或密码不对".trim()==(httpRequest.responseText).trim()){
				alert(httpRequest.responseText);
				return false;
			}else{
				location.href=httpRequest.responseText;
			}
		}
	};
	var postdata="username="+document.getElementById("username").value+"&backurl="+document.getElementById("backurl").value+"&password="+document.getElementById("password").value;
	/* var forms=new FormData();
	forms.append("username", document.getElementById("username").value);
	forms.append("backurl", document.getElementById("backurl").value);
	forms.append("password", document.getElementById("password").value); */
	httpRequest.open("post", document.getElementById("dataFrom").getAttribute("action"),true);
	httpRequest.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
	httpRequest.send(postdata);
}
function createXMLHttpRequest(){
	var xmlHttp;
    if(window.ActiveXObject)
    {
        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
    } 
    else if(window.XMLHttpRequest)
    {
        xmlHttp = new XMLHttpRequest();
    }
    return xmlHttp;
}
</script>
</head>
<body>
<form action="login" method="post" id="dataFrom">
	<table>
		<tr>
			<td><input type="hidden" name="backurl" id="backurl" value="${backurl}"/></td>
		</tr>
		<tr>
			<td><input type="text" name="username" id="username"/></td>
		</tr>
		<tr>
			<td><input type="password" name="password" id="password"/></td>
		</tr>
		<tr>
			<td><input type="button" value="登录" onclick="submitData()"/>     <input type="reset" value="重新输入"/></td>
		</tr>
	</table>
</form>
</body>
</html>





猜你喜欢

转载自blog.csdn.net/shuaipu813/article/details/53259292