One 、 Preface

Used in the project SSO, Using open source framework cas It's done . A simple understanding of cas, And learned a little bit   The principle of single sign on , Interested students can also learn , Write a demo Have some fun .

Two 、 Engineering structure

I simulated sso The client and sso The service side , sso-core There are mainly some sso Filters and tool classes needed , Cache and session Some of the shared XML The configuration file , also springmvc What I need is jar Package management .sso-cache Configuration of the redis Cache policy .

3、 ... and 、 Single sign on schematic

A brief description :

User access system 1 Protected resources for , System 1 Found user not logged in , Jump to sso authentication center , And take your own address as a parameter

sso The authentication center found that the user was not logged in , Guide the user to the login page

User enters user name and password to submit login application

sso Authentication center verifies user information , Create users and sso Sessions between certification centers , Called a global session , Create authorization token at the same time

sso The authentication center takes the token to jump to the original request address ( System 1)

System 1 Get token , Go to sso The authentication center verifies whether the token is valid

sso Authentication center verification token , Return valid , Registration system 1

System 1 Use this token to create a session with the user , Called local session , Return to protected resources

User access system 2 Protected resources for

System 2 Found user not logged in , Jump to sso authentication center , And take your own address as a parameter

sso The authentication center found that the user has logged in , Jump back to system 2 The address of , And attach the token

System 2 Get token , Go to sso The authentication center verifies whether the token is valid

sso Authentication center verification token , Return valid , Registration system 2

System 2 Use this token to create a local session with the user , Return to protected resources

Four 、 Single sign on Implementation

1.SSOFilter.java(sso client filter Realization )

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.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import com.alibaba.fastjson.JSONObject;
import com.hjz.sso.utils.RestTemplateUtil; public class SSOFilter implements Filter{ public static Logger logger = LoggerFactory.getLogger(SSOFilter.class); private String SSO_SERVER_URL;
private String SSO_SERVER_VERIFY_URL; @Override
public void init(FilterConfig filterConfig) throws ServletException {
SSO_SERVER_URL = filterConfig.getInitParameter("SSO_SERVER_URL");
SSO_SERVER_VERIFY_URL = filterConfig.getInitParameter("SSO_SERVER_VERIFY_URL");
if(SSO_SERVER_URL == null) logger.error("SSO_SERVER_URL is null.");
if(SSO_SERVER_VERIFY_URL == null) logger.error("SSO_SERVER_VERIFY_URL is null.");
} @Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
// The request contains token, Go to sso-server verification token Whether it works
String authority = null;
if(request.getParameter("token") != null) {
boolean verifyResult = this.verify(request, SSO_SERVER_VERIFY_URL, request.getParameter("token"));
if (verifyResult) {
chain.doFilter(req, res);
return;
} else {
authority = "token->" + request.getParameter("token") + " is invalidate.";
}
} HttpSession session = request.getSession();
if (session.getAttribute("login") != null && (boolean)session.getAttribute("login") == true) {
chain.doFilter(req, res);
return;
}
// Jump to sso authentication center
String callbackURL = request.getRequestURL().toString();
StringBuilder url = new StringBuilder();
url.append(SSO_SERVER_URL).append("?callbackURL=").append(callbackURL);
if(authority != null) {
url.append("&authority=").append(authority);
}
response.sendRedirect(url.toString());
} private boolean verify(HttpServletRequest request, String verifyUrl, String token) {
String result = RestTemplateUtil.get(request, verifyUrl + "?token=" + token, null);
JSONObject ret = JSONObject.parseObject(result);
if("success".equals(ret.getString("code"))) {
return true;
}
logger.error(request.getRequestURL().toString() + " : " + ret.getString("msg"));
return false;
} @Override
public void destroy() {
} }

2.LoginController.java(sso server Sign in controller)

import java.util.UUID;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; @Controller
@RequestMapping("sso")
public class LoginController {
private Logger logger = LoggerFactory.getLogger(LoginController.class); @RequestMapping(value="login", method={RequestMethod.GET, RequestMethod.POST})
public String login(HttpSession session, Model model,
@RequestParam(value="name", required=false) String name,
@RequestParam(value="password", required=false) String password) {
if(name == null && password == null) return "login";
if("admin".equals(name) && "admin".equals(password)) {
String token = UUID.randomUUID().toString();
session.setAttribute("login", true);
session.setAttribute("token", token);
return "index";
} else {
model.addAttribute("error", true);
model.addAttribute("message", " Wrong user name or password .");
return "login";
}
}
}

3.ValidateController.java(sso server verification token controller)

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import com.alibaba.fastjson.JSONObject; @Controller
@RequestMapping("sso")
public class ValidateController { @RequestMapping("verify")
@ResponseBody
public JSONObject verify(HttpServletRequest request, @RequestParam String token) {
HttpSession session = request.getSession();
JSONObject result = new JSONObject();
if(session.getAttribute("token") != null && token.equals(session.getAttribute("token"))) {
result.put("code", "success");
result.put("msg", " Authentication success ");
} else {
result.put("code", "failure");
result.put("msg", "token Has lapsed , Please login again !");
}
return result;
} }

4. stay sso client Add... To the project SSOFilter(web.xml Part of the configuration )

<filter>
<filter-name>ssoFilter</filter-name>
<filter-class>com.hjz.sso.filter.SSOFilter</filter-class>
<init-param>
<param-name>SSO_SERVER_URL</param-name>
<param-value>http://localhost:8088/sso-server/sso/login</param-value>
</init-param>
<init-param>
<param-name>SSO_SERVER_VERIFY_URL</param-name>
<param-value>http://localhost:8088/sso-server/sso/verify</param-value>
</init-param>
</filter> <filter-mapping>
<filter-name>ssoFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

The basic model has come out , start-up sso-client and sso-server( I have been deployed to the same tomcat Next ), Attempt to verify single sign on . When it comes to testing , From the browser cookie View in , You can see localhost There are multiple JSESSIONID. It's no wonder , Tomcat Each of them application Will create their own session conversation . Then the next thing is to solve session The problem of sharing , So we can complete our single sign on .

In order to complete session share , Here are two options . One is  tomcat+redis Realization session share , One is spring session+redis Realization session share . I'm taking the second option here , Please go on to the following steps for details .

5. For every project web.xml add spring session agent filter Configuration of

<!-- session agent -->
<filter>
<filter-name>springSessionRepositoryFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter> <filter-mapping>
<filter-name>springSessionRepositoryFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

6. stay sso-core Add Cache and spring session Of xml To configure (cache-config.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"
default-lazy-init="false"> <description>Cache Common configuration </description>
<bean id="cookieSerializer" class="org.springframework.session.web.http.DefaultCookieSerializer">
<property name="cookiePath" value="/"></property>
</bean> <bean class="com.sso.cache.config.CacheConfig"/> <bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
<property name="maxInactiveIntervalInSeconds" value="1800"></property>
</bean>
</beans>

Here's why there is a definition of cookieSerializer This bean. see RedisHttpSessionConfiguration Source code , Found that it inherited SpringHttpSessionConfiguration, Continue to view source code , Find out SpringHttpSessionConfiguration In the implementation of our configuration spring session agent filter, As shown below .

SpringHttpSessionConfiguration.java
@Bean
public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter(
SessionRepository<S> sessionRepository) {
SessionRepositoryFilter sessionRepositoryFilter = new SessionRepositoryFilter(sessionRepository); sessionRepositoryFilter.setServletContext(this.servletContext);
if (this.httpSessionStrategy instanceof MultiHttpSessionStrategy) {
sessionRepositoryFilter.setHttpSessionStrategy((MultiHttpSessionStrategy) this.httpSessionStrategy);
} else {
sessionRepositoryFilter.setHttpSessionStrategy(this.httpSessionStrategy);
}
return sessionRepositoryFilter;
}

View source code , You can find  SpringHttpSessionConfiguration The default session policy used (httpSessionStrategy) yes CookieHttpSessionStrategy. Keep looking at CookieHttpSessionStrategy Source code , Such as new construction session write in cookie.

public void onNewSession(Session session, HttpServletRequest request, HttpServletResponse response) {
Set sessionIdsWritten = getSessionIdsWritten(request);
if (sessionIdsWritten.contains(session.getId())) {
return;
}
sessionIdsWritten.add(session.getId()); Map sessionIds = getSessionIds(request);
String sessionAlias = getCurrentSessionAlias(request);
sessionIds.put(sessionAlias, session.getId()); String cookieValue = createSessionCookieValue(sessionIds);
this.cookieSerializer.writeCookieValue(new CookieSerializer.CookieValue(request, response, cookieValue));
}

cookieSerializer The default is  DefaultCookieSerializer. see DefaultCookieSerializer Of  writeCookieValue The method is as follows .

public void writeCookieValue(CookieSerializer.CookieValue cookieValue) {
HttpServletRequest request = cookieValue.getRequest();
HttpServletResponse response = cookieValue.getResponse(); String requestedCookieValue = cookieValue.getCookieValue();
String actualCookieValue = requestedCookieValue + this.jvmRoute; Cookie sessionCookie = new Cookie(this.cookieName, actualCookieValue);
sessionCookie.setSecure(isSecureCookie(request));
sessionCookie.setPath(getCookiePath(request));
String domainName = getDomainName(request);
if (domainName != null) {
sessionCookie.setDomain(domainName);
} if (this.useHttpOnlyCookie) {
sessionCookie.setHttpOnly(true);
} if ("".equals(requestedCookieValue)) {
sessionCookie.setMaxAge(0);
} else {
sessionCookie.setMaxAge(this.cookieMaxAge);
}
response.addCookie(sessionCookie);
}

sessionCookie.setPath(getCookiePath(request)); There's a problem here , to glance at getCookiePath Method implementation , as follows .

private String getCookiePath(HttpServletRequest request) {
if (this.cookiePath == null) {
return request.getContextPath() + "/";
}
return this.cookiePath;
}

If you want to achieve single sign on , Don't use the default  cookiePath Value . therefore , I defined a  cookieSerializer Of bean, And designated cookiePath Value . SpringHttpSessionConfiguration The following methods can be used for automatic assembly Our configured cookieSerializer, Instead of using the default .

@Autowired(required = false)
public void setCookieSerializer(CookieSerializer cookieSerializer) {
this.defaultHttpSessionStrategy.setCookieSerializer(cookieSerializer);
}

7. In every project spring Add the following configuration to the public configuration file .

<import resource="classpath*:cache-config.xml"/>

8. Between the back ends rest Request delivery session ID.

private static ResponseEntity<String> request(ServletRequest req, String url, HttpMethod method, Map<String, ?> params) {
HttpServletRequest request = (HttpServletRequest) req;
// obtain header Information
HttpHeaders requestHeaders = new HttpHeaders();
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String key = (String) headerNames.nextElement();
String value = request.getHeader(key);
requestHeaders.add(key, value);
}
HttpEntity<String> requestEntity = new HttpEntity<String>(params != null ? JSONObject.toJSONString(params) : null, requestHeaders);
ResponseEntity<String> rss = restTemplate.exchange(url, method, requestEntity, String.class);
return rss;
}

Use RestTemplate send out rest request , Copy before sending request Medium header Information , Guarantee session ID It can deliver .

9. Last , Start the project , The test results are as follows .

 

http://study.hujunzheng.cn:8000/sso-client-user/ and http://study.hujunzheng.cn:8000/sso-client-org/ Switch access project .

5、 ... and 、 Full project address

https://github.com/hjzgg/SSO

6、 ... and 、 Project demonstration address

http://study.hujunzheng.cn:8000/sso-client-user/

Single sign on Implementation (spring session+redis complete session share ) More articles about

  1. Nginx+Tomcat Set up the cluster ,Spring Session+Redis Realization Session share

    I haven't seen you guys for a long time ! I'm a little busy recently , Blogging is a little bit less , Um. , Try to work harder .OK, Today I bring you a JavaWeb The architecture commonly used in , namely Nginx+Tomcat Build a service cluster , And then through Spring Session+Redi ...

  2. spring boot + redis Realization session share

    This time spring boot + redis Realization session Shared tutorial . stay spring boot In the document , Tell us to add @EnableRedisHttpSession To open spring se ...

  3. Spring Boot+redis Storage session, Meet cluster deployment 、 Distributed system session share

    This article tells spring-boot Use in engineering spring-session Mechanism for security authentication , And through redis Storage session, Meet cluster deployment . Distributed system session share . Link to the original text :https://w ...

  4. CAS Single sign on and spring securtiy Integrate

    explain : This article is mainly based on spring-security Already integrated in the system : 1. You need to create a spring-security.xml File and associated with applicationContext.xml In file :& ...

  5. spring boot + session+redis solve session Sharing issues

    I haven't tried it myself , But I feel reliable after reading this example , And then we did the test , In order to explain . PS: Later, it was verified that , The above example works . We usually save session The value of the inside , It's directly there redis Inside the .

  6. [ to update ] One contains : use RSA JWT(Json Web Token, RSA encryption ) Of OAUTH2.0,HTTP BASIC, Local database validation ,Windows Domain validation , Single sign on Spring Security The configuration file

    There are no comments , I'm to blame for the watch (¬_¬) to update : 2016.05.29: take AuthorizationServer and ResourceServer distributed disposition 2016.05.29: Token Take advantage of Http Ba ...

  7. JAVAEE—— Yicube Mall 10: Use freemarker Static web page 、ActiveMq Synchronous generation of static web pages 、Sso Single sign on system analysis

    1.  Study plan 1. Use freemarker Static web page 2.ActiveMq Synchronous generation of static web pages 2.  Page static have access to Freemarker Static web page . 2.1.  What is? freemarker ...

  8. 【SSO】 Single sign on System

    One . Single sign on system introduction For a development project , Every project must have the function of login . But as the project gets bigger , Bigger , Get bigger . The system may be split into several small systems , Let's take Alipay and Taobao , Let's shop on Taobao , Then you can ...

  9. Single sign on System ---SSO

    1.------------------SSO Introduce --------------------------------- What's the use of eggs ? What's the matter with airplanes ? Look at this picture , There is no problem with a system . If it's a distributed system ...

Random recommendation

  1. docker run mysql

    sudo docker run --name=mysqlserver -e MYSQL_ROOT_PASS=123456 -v /srv/mysql/data:/data/mysql -d -p : ...

  2. Swagger Usage method

    notes : This article is based on Django-rest-swagger 2.0.7 Write in the environment of Refer to the English document : http://django-rest-swagger.readthedocs.io/en/latest/ ...

  3. Android Exception handling in development ( One ):SDK Manager The solution to flashback

    This question has puzzled me for a long time , Not before , Just put it on . Later, I took another afternoon to find a solution , It's finally done ! My solution is to modify android.bat, Direct designation java.exe The position of , You don't have to call find_java ...

  4. Initial solution DLL Basic knowledge

    1.DLL The basic theory stay Windows Operating system , Almost all of the content is based on DLL In the form of . 1.DLL Basic concepts Language program should start from object code (.obj) External reference function , It can be done in two ways —— Static and dynamic links . ...

  5. uva 10047 the monocyle ( 4 d bfs)

    Algorithm guide white book Maintain a four-dimensional array , Step by step, update step by step #include<cstdio> #include<cstring> #include<queue> #includ ...

  6. HDOJ/HDU 2552 A situation of tripartite confrontation (tan() and atan() Method )

    Problem Description MCA There are many talented people in the mountains , Insight into the outside world, the flames of war , Heroes from all walks of life in the mountains decided to go out of the mountains to save the people , Whiskey that swept the audience with questions , Once a high number of ninety-nine extraterrestrial visitors , Yifenfei, who has been making a sword for ten years , blood , disc ...

  7. poj 2782 Bin Packing ( greedy + Two points )

    F -  greedy + Two points Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu   Description ...

  8. hadoop Note it Hive Management of (web Interface mode )

    Hive Management of ( Two ) Hive Management of ( Two ) Web Interface mode Port number 9999 Starting mode :hive --service hwi Access... Through a browser :http://<IP Address >:9999/hwi/ ...

  9. Linux Chapter eight essays -tar / System startup process

    linux Lesson eight 1.tar Reference resources effect : Compress and decompress files .tar It has no compression function . It is implemented by calling compression function . grammar :tar[ Necessary parameters ][ Select parameters ][ file ] Parameters : The necessary parameters are as follows : -A Add compressed file to ...

  10. logging journal

    import logging logging.basicConfig(filename='log.log', format='%(asctime)s - %(name)s - %(levelname) ...