SSO(单点登录)示例
此文为转载文章,出处:https://www.cnblogs.com/jpfss/p/9273680.html
SSO在我们的应用中非常常见,例如我们在OA系统登录了,我们就可以直接进入采购系统,不需要再登录了,这样使我们非常方便。现在网上也有很多实现方法,于是乎我也想写一个看看。我主要用到的是cookie的机制。在此,分享给大家, 同时提供源代码下载。
进入主题:
工程说明
SSO的实现一般是会有一个SSO Server,也会叫认证中心,同时也会有被认证的系统,如OA系统、采购系统等,他们就相当于SSO Server的client。
为了更形象体现SSO,我写的SSO是有三个工程:一个SSO Server端口为8081,一个OA系统端口为8082,一个采购系统端口为8083。如图:
流程介绍
在整个SSO流程当,有两个流程非常重要,第一个是用户没有登录系统到登录系统的过程;第二是用户在一个系统当中已经登录(例如在OA系统中登录 了),但又想进入另一个系统(例如进入PRO系统)的过程,如果把这两个过程搞定了,那么SSO也就搞定了。我画了两幅图来说明这两个过程。
先看用户没有登录系统到登录系统的过程,如图:
1:用户通过URL访问OA系统。
2:在OA系统中的filter发现这个URL没有ticket(你暂且就把ticket看做是门票),此时就会跳转到SSO Server。
3:SSO Server中的filter发现该客户端中的cookie中没有相应信息,也即是一个没有登录的用户,那么会跳转到登录页面。
4:用户在登录页面填写相应信息,然后通过post方式提交到SSO Server中。
5:SSO Server会校验用户信息(我为了快,我的校验方式就是要用户名为:cloud,同时密码为:cloud),同时在cookie中放username。
6:将生成ticket和username放到JVMCache中,在实际项目应该放到Memcached中,它的用处等下分析。
7,8:就是在用户访问OA系统的URL基础上加上了一个ticket参数,这样跳转到OA系统。
(此时进入OA系统时,filter发现URL是带ticket的,则filter会根据带过来的ticket并通过HttpClient的形式去调用SSO Server中的TicektServlet,这样就会返回用户名,其实这个用户名就是从JVMCache拿到的,同时马上将这个ticket从JVMCache中移除,这样保证一个ticket只会用一次,然后把返回的用户名放到session中)
9:session中有了用户名,说明用户登录成功了,则会去本应该返问的servlet。
10,11:将OA系统返回的视图给用户。
第二过程,用户已经登录成功了,但要访问另一个系统,如图:
1:用户通过URL访问PRO系统。
2:在PRO系统中的filter发现这个URL没有ticket,此时就会跳转到SSO Server。此时,由于用户登录了,所以cookie中有相应的信息(例如用户名),此时SSO Server中的filter会生成一个ticket。
3:将生成的ticket和username放到JVMCache中。
4:就是在用户访问PRO系统的URL基础上加上了一个ticket参数,这样跳转到PRO系统。
(此时进入PRO系统时,filter发现URL是带ticket的,则filter会根据带过来的ticket并通过HttpClient的形式去调用SSO Server中的TicektServlet,这样就会返回用户名,其实这个用户名就是从JVMCache拿到的,同时马上将这个ticket从JVMCache中移除,这样保证一个ticket只会用一次,然后把返回的用户名放到session中)
5:session中有了用户名,说明用户登录成功了,则会去本应该返问的servlet。
5,7:将PRO系统返回的视图给用户。
关键代码
先看SSO Server工程中的代码:
pom.xml
(注意:端口为8081)
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cloud.sso.server</groupId>
<artifactId>sso-server</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>sso-server Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>sso-server</finalName>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.9.v20130131</version>
<configuration>
<stopKey>stop</stopKey>
<stopPort>6000</stopPort>
<webAppConfig>
<contextPath>/sso</contextPath>
</webAppConfig>
<scanIntervalSeconds>4</scanIntervalSeconds>
<connectors>
<connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
<port>8081</port>
<maxIdleTime>60000</maxIdleTime>
</connector>
</connectors>
</configuration>
</plugin>
</plugins>
</build>
</project>
SSO Server中的filter
SSOServerFilter.java
package com.cloud.sso.server.filter; import java.io.IOException; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.cloud.sso.server.JVMCache; public class SSOServerFilter implements Filter { @Override
public void destroy() {
} @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String service = request.getParameter("service");
String ticket = request.getParameter("ticket");
Cookie[] cookies = request.getCookies();
String username = "";
if (null != cookies) {
for (Cookie cookie : cookies) {
if ("sso".equals(cookie.getName())) {
username = cookie.getValue();
break;
}
}
} if (null == service && null != ticket) {
filterChain.doFilter(servletRequest, servletResponse);
return;
} if (null != username && !"".equals(username)) {
long time = System.currentTimeMillis();
String timeString = username + time;
JVMCache.TICKET_AND_NAME.put(timeString, username);
StringBuilder url = new StringBuilder();
url.append(service);
if (0 <= service.indexOf("?")) {
url.append("&");
} else {
url.append("?");
}
url.append("ticket=").append(timeString);
response.sendRedirect(url.toString());
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
} @Override
public void init(FilterConfig arg0) throws ServletException {
} }
两个servlet:
LoginServlet.java
package com.cloud.sso.server.servlet; import java.io.IOException; import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.cloud.sso.server.JVMCache; public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = -3170191388656385924L; @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
} @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
String service = request.getParameter("service"); if ("cloud".equals(username) && "cloud".equals(password)) {
Cookie cookie = new Cookie("sso", username);
cookie.setPath("/");
response.addCookie(cookie); long time = System.currentTimeMillis();
String timeString = username + time;
JVMCache.TICKET_AND_NAME.put(timeString, username); if (null != service) {
StringBuilder url = new StringBuilder();
url.append(service);
if (0 <= service.indexOf("?")) {
url.append("&");
} else {
url.append("?");
}
url.append("ticket=").append(timeString);
response.sendRedirect(url.toString());
} else {
response.sendRedirect("/sso/index.jsp");
}
} else {
response.sendRedirect("/sso/index.jsp?service=" + service);
}
} }
TicketServlet.java
package com.cloud.sso.server.servlet; import java.io.IOException;
import java.io.PrintWriter; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.cloud.sso.server.JVMCache; public class TicketServlet extends HttpServlet {
private static final long serialVersionUID = 5964206637772848290L; @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
super.doGet(request, response);
} @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String ticket = request.getParameter("ticket");
String username = JVMCache.TICKET_AND_NAME.get(ticket);
JVMCache.TICKET_AND_NAME.remove(ticket);
PrintWriter writer = response.getWriter();
writer.write(username);
} }
JVMCache.java
package com.cloud.sso.server; import java.util.HashMap;
import java.util.Map; public class JVMCache { public static Map<String, String> TICKET_AND_NAME = new HashMap<String, String>();
}
web.xml
<?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" xmlns:jsp="http://java.sun.com/xml/ns/javaee/jsp" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list> <filter>
<filter-name>ssoServerFilter</filter-name>
<filter-class>com.cloud.sso.server.filter.SSOServerFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ssoServerFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.cloud.sso.server.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/user/login</url-pattern>
</servlet-mapping> <servlet>
<servlet-name>ticket</servlet-name>
<servlet-class>com.cloud.sso.server.servlet.TicketServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ticket</servlet-name>
<url-pattern>/ticket</url-pattern>
</servlet-mapping>
</web-app>
下面是OA系统中的代码:
pom.xml
(注意:端口为8082)
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cloud.sso.oa</groupId>
<artifactId>sso-oa</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>sso-oa Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
</dependencies>
<build>
<finalName>sso-oa</finalName>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.9.v20130131</version>
<configuration>
<stopKey>stop</stopKey>
<stopPort>6000</stopPort>
<webAppConfig>
<contextPath>/oa</contextPath>
</webAppConfig>
<scanIntervalSeconds>4</scanIntervalSeconds>
<connectors>
<connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
<port>8082</port>
<maxIdleTime>60000</maxIdleTime>
</connector>
</connectors>
</configuration>
</plugin>
</plugins>
</build>
</project>
OA系统中的filter:
SSOClientFilter.java
package com.cloud.sso.oa.filter; import java.io.IOException;
import java.net.URLEncoder; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod; public class SSOClientFilter implements Filter { @Override
public void destroy() {
} @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpSession session = request.getSession();
String username = (String) session.getAttribute("username");
String ticket = request.getParameter("ticket");
String url = URLEncoder.encode(request.getRequestURL().toString(), "UTF-8"); if (null == username) {
if (null != ticket && !"".equals(ticket)) {
PostMethod postMethod = new PostMethod("http://localhost:8081/sso/ticket");
postMethod.addParameter("ticket", ticket);
HttpClient httpClient = new HttpClient();
try {
httpClient.executeMethod(postMethod);
username = postMethod.getResponseBodyAsString();
postMethod.releaseConnection();
} catch (Exception e) {
e.printStackTrace();
}
if (null != username && !"".equals(username)) {
session.setAttribute("username", username);
filterChain.doFilter(request, response);
} else {
response.sendRedirect("http://localhost:8081/sso/index.jsp?service=" + url);
}
} else {
response.sendRedirect("http://localhost:8081/sso/index.jsp?service=" + url);
}
} else {
filterChain.doFilter(request, response);
}
} @Override
public void init(FilterConfig arg0) throws ServletException {
} }
OAServlet.java
package com.cloud.sso.oa.servlet; import java.io.IOException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class OAServlet extends HttpServlet {
private static final long serialVersionUID = 3615122544373006252L; @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/jsp/welcome.jsp").forward(request, response);
} @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
} }
web.xml
<?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" xmlns:jsp="http://java.sun.com/xml/ns/javaee/jsp" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list> <filter>
<filter-name>ssoClientFilter</filter-name>
<filter-class>com.cloud.sso.oa.filter.SSOClientFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ssoClientFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <servlet>
<servlet-name>list</servlet-name>
<servlet-class>com.cloud.sso.oa.servlet.OAServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>list</servlet-name>
<url-pattern>/list</url-pattern>
</servlet-mapping>
</web-app>
下面是PRO系统的代码:
pom.xml
(注意:端口为8083)
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cloud.sso.pro</groupId>
<artifactId>sso-pro</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>sso-pro Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
</dependencies>
<build>
<finalName>sso-pro</finalName>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.9.v20130131</version>
<configuration>
<stopKey>stop</stopKey>
<stopPort>6000</stopPort>
<webAppConfig>
<contextPath>/pro</contextPath>
</webAppConfig>
<scanIntervalSeconds>4</scanIntervalSeconds>
<connectors>
<connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
<port>8083</port>
<maxIdleTime>60000</maxIdleTime>
</connector>
</connectors>
</configuration>
</plugin>
</plugins>
</build>
</project>
PRO系统中的filter
SSOClientFilter.java
package com.cloud.sso.pro.filter; import java.io.IOException;
import java.net.URLEncoder; import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod; public class SSOClientFilter implements Filter { @Override
public void destroy() {
} @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
HttpSession session = request.getSession();
String username = (String) session.getAttribute("username");
String ticket = request.getParameter("ticket");
String url = URLEncoder.encode(request.getRequestURL().toString(), "UTF-8"); if (null == username) {
if (null != ticket && !"".equals(ticket)) {
PostMethod postMethod = new PostMethod("http://localhost:8081/sso/ticket");
postMethod.addParameter("ticket", ticket);
HttpClient httpClient = new HttpClient();
try {
httpClient.executeMethod(postMethod);
username = postMethod.getResponseBodyAsString();
postMethod.releaseConnection();
} catch (Exception e) {
e.printStackTrace();
}
if (null != username && !"".equals(username)) {
session.setAttribute("username", username);
filterChain.doFilter(request, response);
} else {
response.sendRedirect("http://localhost:8081/sso/index.jsp?service=" + url);
}
} else {
response.sendRedirect("http://localhost:8081/sso/index.jsp?service=" + url);
}
} else {
filterChain.doFilter(request, response);
}
} @Override
public void init(FilterConfig arg0) throws ServletException {
} }
ProServlet.java
package com.cloud.sso.pro.servlet; import java.io.IOException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class ProServlet extends HttpServlet {
private static final long serialVersionUID = -1334093914490423930L; @Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/jsp/welcome.jsp").forward(request, response);
} @Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
super.doPost(request, response);
} }
web.xml
<?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" xmlns:jsp="http://java.sun.com/xml/ns/javaee/jsp" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list> <filter>
<filter-name>ssoClientFilter</filter-name>
<filter-class>com.cloud.sso.pro.filter.SSOClientFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ssoClientFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <servlet>
<servlet-name>list</servlet-name>
<servlet-class>com.cloud.sso.pro.servlet.ProServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>list</servlet-name>
<url-pattern>/list</url-pattern>
</servlet-mapping>
</web-app>
运行结果:
1:分别启动这三个工程。
2:访问OA系统,URL:http://localhost:8082/oa/list
3:这样到登录页面,如图:

4:用户名为:cloud,密码为:cloud,点击登录则会显示,如图:

5:然后去进入PRO系统,URL:http://localhost:8083/pro/list,则就不需要登录了,直接进入,如图:

SSO(单点登录)示例的更多相关文章
- [sso] 单点登录认证流程
一.流程说明 第一步:访问cas过滤链接ssoLogin,拼凑定向到 CAS_SERVER 获取ticket的URL 第二步:CAS_SERVER校验用户信息,生成Ticket 第三步:重新定向到访问 ...
- cas sso单点登录系列4_cas-server登录页面自定义修改过程(jsp页面修改)
转:http://blog.csdn.net/ae6623/article/details/8861065 SSO单点登录系列4:cas-server登录页面自定义修改过程,全新DIY. 目标: ...
- SSO单点登录系列4:cas-server登录页面自定义修改过程(jsp页面修改)
落雨 cas 单点登录 SSO单点登录系列4:cas-server登录页面自定义修改过程,全新DIY. 目标: 下面是正文: 打开cas的默认首页,映入眼帘的是满眼的中文and英文混杂体,作为一 ...
- SSO单点登录学习总结(3)—— 基于CAS实现单点登录实例
第一: 本demo在一个机器上实现(三个虚拟主机),来看SSO单点登录实例(我们可以布到多个机器上使用都是同一个道理的),一个服务器主机,和两个客户端虚拟主机 [html] view plaincop ...
- 使用 JSONP 实现简单的 SSO 单点登录
SSO 即 Single Sign On(单点登录). 一.二级域名之间的单点登录 不需要用到JSONP 或者 p3p 协议,直接使用 COOKIE 就行了,因为顶级域名相同就能实现 COOKIE ...
- CAS实现SSO单点登录原理
1. CAS 简介 1.1. What is CAS ? CAS ( Central Authentication Service ) 是 Yale 大学发起的一个企业级的.开源的项目,旨 ...
- php sso单点登录原理阐述
原理:就是用户登录了单点登录系统(sso)之后,就可以免登录形式进入相关系统: 实现: 点击登录跳转到SSO登录页面并带上当前应用的callback地址 登录成功后生成COOKIE并将COOKIE传给 ...
- SSO单点登录之跨域问题
第一次写博客,与大家共勉. 这里用到的原理其实非常简单,将cookie存在一个公共的站点的页面上就可以了,这里我们管那个站点叫主站S. 先说说所谓的跨域 环境1:a.xxx.com需要跟b.xxx.c ...
- 学习CAS实现SSO单点登录
学习CAS实现SSO单点登录 网上找了几篇比较详细的教程,在这记录一下: 原理: CAS实现SSO单点登录原理 教程: 1.CAS实现单点登录(SSO)经典完整教程 2.SSO之CAS单点登录实例演示 ...
- CAS实现SSO单点登录原理(转)
1. CAS 简介 1.1. What is CAS ? CAS ( Central Authentication Service ) 是 Yale 大学发起的一个企业级的.开源的项目,旨 ...
随机推荐
- 【数据结构&算法】12-线索二叉树
目录 前言 线索二叉树的概念 线索二叉树的实现 线索二叉树的寻点思路二 类双向链表参考图 参考代码 中序遍历线索化 前言 在<大话数据结构>P190 页中有一句话:其实线索二叉树,就等于是 ...
- CSS基础-行快属性,hover
CSS基础 1.行快属性 在css中有很多标签,分为行内标签,块标签,标签行内块标签,他们有着不同的属性. 块标签 div,ul,li,ol,h1~h6,p 可 ...
- 18.Java 封装详解/多态详解/类对象转型详解
封装概述 简述 封装是面向对象的三大特征之一. 封装优点 提高代码的安全性. 提高代码的复用性. "高内聚":封装细节,便于修改内部代码,提高可维护性. "低耦合&quo ...
- Java String 转成 二位数组
... package str; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; impo ...
- Python 练习 进程
... """ 创建2个进程, 每一个进程都打出当前的时间和进程的标识,持续打十次. """ import multiprocessing ...
- Python 深拷贝和浅拷贝的区别
python的复制,深拷贝和浅拷贝的区别 在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用 ...
- [gym103055H]Grammy and HearthStone
题目即要求构造一个长为$2n$的序列$a_{i}$,满足$\forall 1\le i\le n$,$i$恰好出现两次,假设分别是$a_{x}=a_{y}=i(x<y)$,即要求$y-x=i$ ...
- [loj3503]滚榜
一个小问题:题意中关于$b_{i}$的顺序只需要单调不降即可,相同时可任意选择 考虑$i$优于$j$的条件,即$val_{i}\ge val_{j}+[i>j]$,并记$del_{i,j}=\m ...
- 【Spring】(1)-- 概述
Spring框架 -- 概述 2019-07-07 22:40:42 by冲冲 1. Spring的概念 ① Spring框架的关键词:开源框架.轻量级框架.JavaEE/J2EE开发框架.企业级 ...
- System.Web.Optimization
项目中引用了 System.Web.Optimization 这个程序集,缺少程序集会报错: 命名空间"System.Web"中不存在类型或命名空间名"Optimizat ...