1. 程式人生 > >java單點登入(cookie手寫/cas框架)

java單點登入(cookie手寫/cas框架)

客戶端和伺服器建立聯絡以後就會將sessionid寫入cookie,當客戶端關閉後cookie就會被清除同時伺服器端session也會被銷燬。所以我們登入到伺服器後可以在cookie中寫入我們的登入資訊用於訪問其他頁面時做登入校驗。這種校驗方法和把登入後資訊寫入session中道理基本一樣。

java單點登入利用了cookie機制。每個客戶端系統都維護自己的cookie登入資訊,但是在其中的一個系統中登入了,怎樣將登入資訊寫入其他客戶端系統呢?另外cookie中登入資訊的校驗和登入時使用者名稱密碼的校驗又怎麼處理呢?單點登入一般在訪問客戶端主頁面的時候,客戶端的controller在接受到訪問時,首先檢視本域的cookie中有沒有登入資訊,當發現cookie中沒有登入資訊戶就會返回校驗伺服器login頁面。當發現cookie中存在登入資訊後,該客戶端會將登入資訊傳送給校驗伺服器,後根據校驗伺服器返回的校驗結果決定返回成功登入頁面或者校驗伺服器login頁面。另外在登入成功後需要寫cookie的時候,呼叫所有客戶端的寫cookie方法。這樣所有客戶端cookie的登入資訊都被寫入,在其他客戶端訪問主頁面時發現cookie中有了登入資訊,然後拿著這個資訊去校驗伺服器進行校驗。這樣就可以成功訪問主頁面而不用登入了。

工程結構

ServerLoginController.java

package www.checkServer.com.controller;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import www.checkServer.com.util.CheckUtil;

@Controller
@RequestMapping("/server")
public class ServerLoginController {

	@Autowired
	HttpServletResponse response;
	
	/**
	 * 統一登入
	 * @param form
	 * @return
	 * @throws IOException
	 */
	@ResponseBody
	@RequestMapping("/doLogin")
	public void doLogin(String username,String password) throws IOException{
		boolean ok = CheckUtil.checkLogin(username, password);
		String result = "0";
		if(ok){
			result = "1";
		}
		response.getWriter().println(result);
		response.getWriter().close();
	}
	
	/**
	 * 統一cookie校驗
	 * @param cookieName
	 * @param cookieValue
	 * @throws IOException
	 */
	@ResponseBody
	@RequestMapping("/checkCookie")
	public void checkCookie(String cookieName,String cookieValue) throws IOException{
		boolean ok = CheckUtil.checkCookie(cookieName, cookieValue);
		String result = "0";
		if(ok){
			result = "1";
		}
		response.getWriter().println(result);
		response.getWriter().close();
	}
}

CheckUtil.java

package www.checkServer.com.util;

public class CheckUtil {

	// 測試用username,password
	public static final String USERNAME = "user";
	public static final String PASSWORD="123";
	
	/**
	 * 校驗使用者名稱密碼正確性
	 * @param username
	 * @param password
	 * @return
	 */
	public static boolean checkLogin(String username,String password){
		if(username.equals(USERNAME) && password.equals(PASSWORD)){
			return true;
		}
		return false;
	}
	
	/**
	 * 校驗cookie正確性
	 * @param cookieName
	 * @param cookieValue
	 * @return
	 */
	public static boolean checkCookie(String cookieName,String cookieValue){
		if(cookieName.equals("ssocookie") && cookieValue.equals("sso")){
			return true;
		}
		return false;
	}
}

Client1LoginController.java

package www.client1.com.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import www.client1.com.form.LoginForm;
import www.client1.com.util.Client1Util;

@Controller
@RequestMapping("/client1")
public class Client1LoginController {
	
	@Autowired
	HttpServletRequest request;
	
	@Autowired
	HttpServletResponse response;

	/**
	 * 訪問client1主頁面方法
	 * @return
	 */
	@RequestMapping("/main")
	public ModelAndView main(){
		ModelAndView mv = new ModelAndView();
		
		Cookie[] cookies = request.getCookies();
		if(cookies != null){
			for (Cookie cookie : cookies) {
				if(cookie.getName().equals("ssocookie")){
					Map<String,String> map = new HashMap<String,String>();
					map.put("cookieName", cookie.getName());
					map.put("cookieValue", cookie.getValue());
					String result = Client1Util.doGet("http://www.checkServer.com/sso-cross/server/checkCookie.do",map);
					if(result.equals("1")){
						mv.setViewName("success1");
						return mv;
					}
				}
			}
		}
		
		mv.setViewName("login");
		mv.addObject("gotoUrl", "http://www.client1.com/sso-cross/client1/main.do");
		mv.addObject("path", "client1");
		return mv;
	}
	
	/**
	 * client1的登入方法
	 * @param form
	 * @return
	 */
	@RequestMapping("/doLogin")
	public ModelAndView doLogin(LoginForm form){
		ModelAndView mv = new ModelAndView();
		Map<String,String> map = new HashMap<String,String>();
		map.put("username", form.getUsername());
		map.put("password", form.getPassword());
		String result = Client1Util.doGet("http://www.checkServer.com/sso-cross/server/doLogin.do", map);
		if(result.equals("1")){
			List<String> hiddenUrl = new ArrayList<String>();
			hiddenUrl.add("http://www.client1.com/sso-cross/client1/addCookie.do");
			hiddenUrl.add("http://www.client2.com/sso-cross/client2/addCookie.do");
			mv.addObject("hiddenUrl", hiddenUrl);
			mv.setViewName("success1");
			return mv;
		}
		
		mv.setViewName("login");
		mv.addObject("gotoUrl", "http://www.client1.com/sso-cross/client1/main.do");
		mv.addObject("path", "client1");
		return mv;
	}
	
	/**
	 * client1新增cookie方法
	 */
	@ResponseBody
	@RequestMapping("addCookie")
	public void addCookie(){
		Cookie cookie = new Cookie("ssocookie","sso");
		cookie.setPath("/");
		response.addCookie(cookie);
	}
}

LoginForm.java

package www.client1.com.form;

public class LoginForm {
	private String username;
	private String password;
	private String gotoUrl;
	private String path;
	
	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getGotoUrl() {
		return gotoUrl;
	}
	public void setGotoUrl(String gotoUrl) {
		this.gotoUrl = gotoUrl;
	}
	public String getPath() {
		return path;
	}
	public void setPath(String path) {
		this.path = path;
	}
}

Client1Util.java

package www.client1.com.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

public class Client1Util {

	/**
	 * 向登入伺服器通訊,校驗使用者名稱密碼或者cookie是否存在
	 * @param url
	 * @param map
	 * @return
	 */
	public static String doGet(String url, Map<String, String> map) {
		StringBuffer sb = new StringBuffer();
		HttpURLConnection httpURLConnection = null;
		try {
			StringBuffer t_s = new StringBuffer(url + "?");
			for (Map.Entry<String, String> entry : map.entrySet()) {
				t_s.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
			}

			url = t_s.substring(0, t_s.length() - 1);
			URL urls = new URL(url);

			httpURLConnection = (HttpURLConnection) urls.openConnection();
			httpURLConnection.setRequestMethod("GET");
			httpURLConnection.connect();
			InputStream in = httpURLConnection.getInputStream();
			InputStreamReader isr = new InputStreamReader(in);
			BufferedReader br = new BufferedReader(isr);
			String temp = null;
			while ((temp = br.readLine()) != null) {
				sb.append(temp);
			}
			br.close();
			isr.close();
			in.close();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (httpURLConnection != null) {
				httpURLConnection.disconnect();
			}
		}

		return sb.toString();
	}
}

Client2LoginController.java

package www.client2.com.controller;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import www.client2.com.form.LoginForm;
import www.client2.com.util.Client2Util;

@Controller
@RequestMapping("/client2")
public class Client2LoginController {
	
	@Autowired
	HttpServletRequest request;
	
	@Autowired
	HttpServletResponse response;

	/**
	 * 訪問client2主頁面方法
	 * @return
	 */
	@RequestMapping("/main")
	public ModelAndView main(){
		ModelAndView mv = new ModelAndView();
		
		Cookie[] cookies = request.getCookies();
		if(cookies != null){
			for (Cookie cookie : cookies) {
				if(cookie.getName().equals("ssocookie")){
					Map<String,String> map = new HashMap<String,String>();
					map.put("cookieName", cookie.getName());
					map.put("cookieValue", cookie.getValue());
					String result = Client2Util.doGet("http://www.checkServer.com/sso-cross/server/checkCookie.do",map);
					if(result.equals("1")){
						mv.setViewName("success2");
						return mv;
					}
				}
			}
		}
		
		mv.setViewName("login");
		mv.addObject("gotoUrl", "http://www.client2.com/sso-cross/client2/main.do");
		mv.addObject("path", "client2");
		return mv;
	}
	
	/**
	 * client2的登入方法
	 * @param form
	 * @return
	 */
	@RequestMapping("/doLogin")
	public ModelAndView doLogin(LoginForm form){
		ModelAndView mv = new ModelAndView();
		Map<String,String> map = new HashMap<String,String>();
		map.put("username", form.getUsername());
		map.put("password", form.getPassword());
		String result = Client2Util.doGet("http://www.checkServer.com/sso-cross/server/doLogin.do", map);
		if(result.equals("1")){
			List<String> hiddenUrl = new ArrayList<String>();
			hiddenUrl.add("http://www.client1.com/sso-cross/client1/addCookie.do");
			hiddenUrl.add("http://www.client2.com/sso-cross/client2/addCookie.do");
			mv.addObject("hiddenUrl", hiddenUrl);
			mv.setViewName("success2");
			return mv;
		}
		
		mv.setViewName("login");
		mv.addObject("gotoUrl", "http://www.client2.com/sso-cross/client2/main.do");
		mv.addObject("path", "client2");
		return mv;
	}
	
	/**
	 * client2新增cookie方法
	 */
	@ResponseBody
	@RequestMapping("addCookie")
	public void addCookie(){
		Cookie cookie = new Cookie("ssocookie","sso");
		cookie.setPath("/");
		response.addCookie(cookie);
	}
}

Client2Util.java

package www.client2.com.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

public class Client2Util {
	
	/**
	 * 向登入伺服器通訊,校驗使用者名稱密碼或者cookie是否存在
	 * @param url
	 * @param map
	 * @return
	 */
	public static String doGet(String url,Map<String,String> map){
		StringBuffer sb = new StringBuffer();
		HttpURLConnection httpURLConnection = null;
		try{
			StringBuffer t_s = new StringBuffer(url + "?");
			for (Map.Entry<String,String> entry: map.entrySet()) {
				t_s.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
			}
			
			url = t_s.substring(0,t_s.length()-1);
			URL urls = new URL(url);
			
			httpURLConnection = (HttpURLConnection) urls.openConnection();
			httpURLConnection.setRequestMethod("GET");
			httpURLConnection.connect();
			InputStream in = httpURLConnection.getInputStream();
			InputStreamReader isr = new InputStreamReader(in);
			BufferedReader br = new BufferedReader(isr);
			String temp = null;
			while((temp = br.readLine()) != null){
				sb.append(temp);
			}
			br.close();
			isr.close();
			in.close();
		}catch(IOException e){
			e.printStackTrace();
		}finally{
			if(httpURLConnection != null){
				httpURLConnection.disconnect();
			}
		}
		
		return sb.toString();
	}
}

spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-4.3.xsd 
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-4.3.xsd 
      http://www.springframework.org/schema/mvc
      http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">

</beans>

springMVC.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-4.3.xsd 
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-4.3.xsd 
      http://www.springframework.org/schema/mvc
      http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd">

	<mvc:annotation-driven></mvc:annotation-driven>

	<context:component-scan base-package="www.checkServer.com.controller"></context:component-scan>
	<context:component-scan base-package="www.client1.com.controller"></context:component-scan>
	<context:component-scan base-package="www.client2.com.controller"></context:component-scan>

	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix">
			<value>/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>
</beans>

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">

	<!-- 配置Spring -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<!-- mybatis的配置檔案要寫到這裡不能寫到springMVC下面,否則在動態掃描Bean的時候會出現找不到mybatis定義的mapper的情況 -->
		<param-value>classpath*:spring.xml</param-value>
	</context-param>

	<!-- 配置Spring mvc -->
	<servlet>
		<servlet-name>springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath*:springMVC.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	
	<servlet-mapping>
		<servlet-name>springmvc</servlet-name>
		<url-pattern>*.do</url-pattern>
	</servlet-mapping>

</web-app> 

login.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()+ path + "/";
%>
<html>
	<head>
		<base href="<%=basePath%>">
		<title>登入</title>
	</head>
	
	<body>
		<center>
			<h1>請登入</h1>
			<form action="./${path}/doLogin.do" method="post">
				<span>使用者名稱:</span><input type="text" name="username" />
				<span>密碼</span><input type="password" name="password" />
				<input type="submit" value="登入" />
				
				<input type="hidden" name="gotoUrl" value="${gotoUrl}" />
			</form>
		</center>
	</body>
</html>

success1.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()+ path + "/";
%>
<html>
	<head>
		<base href="<%=basePath%>">
		<title>client1登入成功</title>
	</head>
	
	<body>
		<center>
			<h1>client1登入成功</h1>
		</center>
		
		<c:forEach var="url" items="${hiddenUrl}">
			<iframe src="${url}" width="0px" height="0px" ></iframe>
		</c:forEach>
		
	</body>
</html>

success2.jsp

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()+ path + "/";
%>
<html>
	<head>
		<base href="<%=basePath%>">
		<title>client2登入成功</title>
	</head>
	
	<body>
		<center>
			<h1>client2登入成功</h1>
		</center>
		
		<c:forEach var="url" items="${hiddenUrl}">
			<iframe src="${url}" width="0px" height="0px" ></iframe>
		</c:forEach>
	</body>
</html>

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com</groupId>
	<artifactId>sso-cross</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<dependencies>

		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>

		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>4.3.13.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>4.3.13.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.3.13.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>4.3.13.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>4.3.13.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-expression</artifactId>
			<version>4.3.13.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>4.3.13.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-oxm</artifactId>
			<version>4.3.13.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>4.3.13.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>4.3.13.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jms</artifactId>
			<version>4.3.13.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>4.3.13.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>4.3.13.RELEASE</version>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.8.9</version>
		</dependency>

		<dependency>
			<groupId>commons-io</groupId>
			<artifactId>commons-io</artifactId>
			<version>2.5</version>
		</dependency>

		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib</artifactId>
			<version>3.2.2</version>
		</dependency>
	</dependencies>

</project>

以上是手寫部分。

當然sso的實現方法還有使用cas的方式。使用還是比較簡單的,可以參照下面幾篇文章。

https://www.cnblogs.com/ruiati/p/6265194.html

https://www.cnblogs.com/notDog/p/5275149.html

https://www.cnblogs.com/13jhzeng/p/5722153.html

如果想修改登入介面樣式可以先將cas-server-webapp-3.5.2.1.war匯入到eclipse,修改夠打包釋出即可。