单点登录(因为原理一样,所以没有实现注销)
2017-05-01 16:38 甘雨路 阅读(927) 评论(0) 编辑 收藏 举报单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
实现原理:
1)客户访问系统,通过拦截访问地址,判断该用户是否登录了,如果已经在该登录过了,则可直接访问;否则,携带访问路径去验证中心。
2)然后验证中心,判断携带过来的路径是否合法,如果不合法,跳转到错误页面;反之,进行下一步令牌验证
3)如果持有令牌,则已经在其它相关系统登录过了,不需要再去登录页面了,然后携带已经(在其它相关系统)登录过的信息返回原来的系统,进行访问。如果没有令牌,该用户还没有登录过,跳转到登录页面
4)在登录页面进行登录,登录后,发放令牌,并且携带已登录信息返回原系统。
5)返回原系统后,保存令牌和已登录的信息
具体代码如下(本人在两台计算机上跑了两份代码,你可以在一台计算上支持多个Tomcat,让两份代码分别交个两个Tomcat运行,端口不冲突即可)
系统一的代码如下(其中验证系统嵌入在系统一中):
package sysone.zr.com.controller; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.UUID; import javax.enterprise.inject.Default; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class VerifyController { private static List<String> urls = new ArrayList<String>(); // 来源的连接地址 private String from=null; static{ urls.add("http://192.168.10.105:8080/lf/online/welcome.htm"); urls.add("http://192.168.10.77:8080/zlf/online/welcome.htm"); } @RequestMapping("/verifyInfo.htm") public String verifyInfo(HttpServletRequest request,HttpServletResponse response, @RequestParam(value="url",required=false,defaultValue="") String url, @RequestParam(value="token",required=false,defaultValue="") String token) throws IOException{ System.out.println("==url:"+url); System.out.println("==token:"+token); if ("".equals(url)) { return "error"; } // 判断是否属于相关系统的URL boolean isRight = false; for (String str : urls) { if (url.equals(str)) { isRight = true; } } // 不属于服务范畴,跳转到错误页面 if (isRight==false) { return "error"; } // 如果没有登录,就没有令牌,去登录页面 if ("".equals(token)) { from = url; return "login"; }else { String identifier = (String)request.getSession().getAttribute("token"); // 验证通过(已经在其它系统登录过) if (token.equals(identifier)) { // 返回原来的系统 response.sendRedirect(url+"?isLogin=true&token="+token); } } return "login"; } @RequestMapping("login.htm") public void login(HttpServletResponse response,HttpServletRequest request, @RequestParam(value="username",required=false,defaultValue="") String username, @RequestParam(value="password",required=false,defaultValue="") String password) throws IOException{ // 实际开发应该去数据库验证,再次忽略该步骤,错误返回相应提示也在此忽略 if(username.equals("lf") && password.equals("lf")){ String token = UUID.randomUUID().toString(); // 保存令牌 request.getSession().setAttribute("token", token); System.out.println("--from:"+from); // 重定向(携带参数返回原系统) response.sendRedirect(from+"?isLogin=true&token="+token); } } }
package sysone.zr.com.controller; import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/lf/online") public class WelcomeController { /** * 进入页面 * @return */ @RequestMapping("/welcome.htm") public String comeInPage(Model model,HttpServletRequest request){ String token = (String)request.getSession().getAttribute("token"); System.out.println("令牌:"+token); model.addAttribute("token", token); return "welcome"; } }
package sysone.zr.com.interception; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class URLHandler implements HandlerInterceptor{ @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { // TODO Auto-generated method stub } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object arg2, ModelAndView arg3) throws Exception { } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception { System.out.println("======进入拦截器======="+request.getRequestURI() ); System.out.println(request.getRequestURL()); // 获取session HttpSession session = request.getSession(); String isLogin = (String)session.getAttribute("isLogin"); System.out.println(isLogin); isLogin = isLogin==null ? "":isLogin; // 判断曾经是否登陆过该系统,如果登陆过往下执行,否则去验证系统 if ("".equals("")) { // 获取相关参数 isLogin = request.getParameter("isLogin"); String token = request.getParameter("token"); isLogin = isLogin==null ? "" : isLogin; token= token == null ? "" :token; /* * 如果是从验证系统跳转过来,便携带相关参数 * 如果验证通过,保存数据 */ if ("true".equals(isLogin) && !"".equals(token)) { session.setAttribute("isLogin", isLogin); session.setAttribute("token", token); }else{ // 获取路径 StringBuffer url = request.getRequestURL(); response.sendRedirect("http://192.168.10.105:8080/verifyInfo.htm?token="+token+"&url="+url); } } return true; } }
<?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:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd" > <!-- 包扫描 --> <context:component-scan base-package="sysone.zr.com" /> <!-- 开启Springmvc注解驱动 --> <mvc:annotation-driven /> <!-- SpringMVC视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> <!-- 拦截器 --> <bean id="urlhandler" class="sysone.zr.com.interception.URLHandler"></bean> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/lf/online/**"/> <ref bean="urlhandler"/> </mvc:interceptor> </mvc:interceptors> </beans>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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> </head> <body> <h1>抱歉找不到相关服务</h1> </body> </html>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!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> </head> <body> <form action="login.htm" method="post"> 用户名:<input name="username" /><br> 密码:<input name="password" type="password" /><br> <input type="submit" value="login"/> </form> </body> </html>
<%@ 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> </head> <body> <h1>欢迎进入系统1</h1> <a href="http://192.168.10.77:8080/zlf/online/welcome.htm?token=${token }">访问系统2</a> </body> </html>
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <!-- 配置springmvc核心 Servlet--> <servlet> <servlet-name>pringmvc</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> </servlet> <servlet-mapping> <servlet-name>pringmvc</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> <!-- END 配置springmvc核心 Servlet--> </web-app>
系统二的代码如下:
package sysone.zr.com.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller @RequestMapping("/zlf/online") public class WelcomeController { /** * 进入页面 * @return */ @RequestMapping("/welcome.htm") public String comeInPage(){ return "welcome"; } }
package sysone.zr.com.interception; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; public class URLHandler implements HandlerInterceptor{ @Override public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { // TODO Auto-generated method stub } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object arg2, ModelAndView arg3) throws Exception { } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object arg2) throws Exception { System.out.println("======进入拦截器2======="+request.getRequestURI() ); System.out.println(request.getRequestURL()); // 获取session HttpSession session = request.getSession(); String isLogin = (String)session.getAttribute("isLogin"); System.out.println(isLogin); isLogin = isLogin==null ? "":isLogin; // 判断曾经是否登陆过该系统,如果登陆过往下执行,否则去验证系统 if ("".equals("")) { // 获取相关参数 isLogin = request.getParameter("isLogin"); String token = request.getParameter("token"); isLogin = isLogin==null ? "" : isLogin; token= token == null ? "" :token; /* * 如果是从验证系统跳转过来,便携带相关参数 * 如果验证通过,保存数据 */ if ("true".equals(isLogin) && !"".equals(token)) { session.setAttribute("isLogin", isLogin); session.setAttribute("token", token); }else{ // 获取路径 StringBuffer url = request.getRequestURL(); response.sendRedirect("http://192.168.10.105:8080/verifyInfo.htm?token="+token+"&url="+url); } } return true; } }
<?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:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd" > <!-- 包扫描 --> <context:component-scan base-package="sysone.zr.com" /> <!-- 开启Springmvc注解驱动 --> <mvc:annotation-driven /> <!-- SpringMVC视图解析器 --> <bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> <!-- 拦截器 --> <bean id="urlhandler" class="sysone.zr.com.interception.URLHandler"></bean> <mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/zlf/online/**"/> <ref bean="urlhandler"/> </mvc:interceptor> </mvc:interceptors> </beans>
<%@ 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>系统2首页</title> </head> <body> <h1>欢迎进入系统2</h1> <a href="http://192.168.10.105:8080/lf/online/welcome.htm?token=${token }">访问系统1</a> </body> </html>
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <!-- 配置springmvc核心 Servlet--> <servlet> <servlet-name>pringmvc</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> </servlet> <servlet-mapping> <servlet-name>pringmvc</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> <!-- END 配置springmvc核心 Servlet--> </web-app>