单点登录介绍
SSO英文全称Single Sign On,单点登录。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次主要的登录映射到其他应用中用于同一个用户的登录的机制。它是目前比较流行的企业业务整合的解决方案之一。

为什么要单点登录

在平常写案例的时候,如果只有一个web工程。如果要访问用户相关信息,那么我们通常会写个拦截器,从session中看能不能取到用户信息,如果不能那么需要返回到登录页面,用户登录后将用户信息保存到session中,那么在此访问用户中心就没问题了。然后这种做法在一个web工程中是没问题的。

如果系统是分布式的情况呢,比如拿商城来说,它是一个分布式的,什么会员模块,商品管理模块,购物车模块,订单模块等。如果还用上面那张验证方式的话,访问a模块的话发现没登录,然后跳转页面登录了,信息存入session中,如果下次访问的是b模块,由于模块都是存在于不同的服务器session中肯定没有登录用户信息,那么肯定是访问不通过要求重新登录。而且,为了解决高并发还得进行集群,即使是两次访问同一模块,也有可能访问的是集群中的另外一台服务器,这样就存在多次要求登录的问题。

解决:我们可以整个Session服务器(SSO系统)专门用来处理登录问题,这样用户每次访问用户中心的时候都来该服务器判断用户有没有登录,如果登录了放行,没有登录就跳转到登录页面,登录后将用户信息保存到Session服务器中,我们需要用redis来模拟从前的session,以前用户信息存入redis中,这里我们就将用户信息存入redis中。

那么怎么存,用什么做key什么做value呢?在一个web工程的时候,用户信息存入session是这样设置的session.setArrtribute(“admin”,user),获取则是session.getAttribute(“admin”);

很自然的想到用用户id做为key,但是不要这样做,因为这样是不能区分不同的连接的,比如你在A电脑登录了tom这个账号,信息存入redis中了且key为tom的id。然后换个电脑B,但是不直接登录却直接访问用户中心(比如订单结算),那么能不能访问呢?是可以访问的,因为redis中存了这么个键值对啊,然后就能取出来用户信息说明已经登录了,所以肯定给访问。但是这样是不合理的,不应该换电脑登录还能直接访问用户中心。
用一个web工程使用tomcat服务器的时候,tomcat是怎么区分不同连接的呢,实际上每次获取session的时候tomcat会生成一个JSESSIONID的作为标识,然后返回给浏览器存到Cookie里面,下次再访问的时候会带着这个JSESSIONID来访问,然后tomcat拿到这个标识会去寻找对应的session,再从中取出用户信息,这样如果换电脑B了,B浏览器里面是没有这个JSESSIONID的,那么在服务端也找不到对应的session更别说取到用户信息了,所以要求重新登录。
既然是打算用redis来模拟session,那么也可以这样做。用户每次登录的时候都会生成一个唯一的表示token,用它来作为key,用户信息作为value,然后将token存到Cookie里面返给浏览器。用户下次
访问用户中心的时候,从Cookie里面取token,再用token从redis中取用户信息,来判断是否允许访问用户中心。
这样做,只要用户换电脑登录了,那么Cookie里面就没有这个token就查不到用户信息所以必须要重新登录了,分析到这基本上也能做了。

前期准备好的jar包
e3-common(jar)里面存放的是一些工具类
e3-manager-pojo(jar)里面存放的是mybatis逆向工程生成的Mapper和映射文件。
1、SSO工程搭建
e3-sso(pom)
|–e3-sso-interface(jar)
|–e3-sso-service(war)
e3-sso-web(war)

e3-sso需要引入的jar包
pom.xml中

<groupId>cn.e3mall</groupId><artifactId>e3-sso</artifactId><version>0.0.1-SNAPSHOT</version><packaging>pom</packaging><modules><module>e3-sso-interface</module><module>e3-sso-service</module></modules><dependencies><dependency><groupId>cn.e3mall</groupId><artifactId>e3-common</artifactId><version>0.0.1-SNAPSHOT</version></dependency></dependencies><!-- 配置tomcat插件 --><build><plugins><plugin><!-- 配置Tomcat插件 --><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><configuration><path>/</path><!-- 表示访问时候不带工程名的 --><port>8087</port></configuration></plugin></plugins></build>

e3-sso-interface引入jar包
pom.xml中

<parent><groupId>cn.e3mall</groupId><artifactId>e3-sso</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>e3-sso-interface</artifactId><dependencies><dependency><groupId>cn.e3mall</groupId><artifactId>e3-manager-pojo</artifactId><version>0.0.1-SNAPSHOT</version></dependency></dependencies>

e3-sso-service引入jar包
pom.xml中

<parent><groupId>cn.e3mall</groupId><artifactId>e3-sso</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>e3-sso-service</artifactId><packaging>war</packaging><dependencies><dependency><groupId>cn.e3mall</groupId><artifactId>e3-manager-dao</artifactId><version>0.0.1-SNAPSHOT</version></dependency><dependency><groupId>cn.e3mall</groupId><artifactId>e3-sso-interface</artifactId><version>0.0.1-SNAPSHOT</version></dependency><!-- Spring --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jms</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency><!-- dubbo相关 --><dependency><groupId>com.alibaba</groupId><artifactId>dubbo</artifactId><exclusions><exclusion><groupId>org.springframework</groupId><artifactId>spring</artifactId></exclusion><exclusion><groupId>org.jboss.netty</groupId><artifactId>netty</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId></dependency><dependency><groupId>com.github.sgroschupf</groupId><artifactId>zkclient</artifactId></dependency></dependencies>

spring配置文件1中:配置数据源以及spring与mybatis整合

<!-- 数据库连接池 --><!-- 加载配置文件 --><context:property-placeholder location="classpath:conf/*.properties" /><!-- 数据库连接池 --><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" /><property name="driverClassName" value="${jdbc.driver}" /><property name="maxActive" value="10" /><property name="minIdle" value="5" /></bean><!-- 让spring管理sqlsessionfactory 使用mybatis和spring整合包中的 --><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><!-- 数据库连接池 --><property name="dataSource" ref="dataSource" /><!-- 加载mybatis的全局配置文件 --><property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" /></bean><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="cn.e3mall.mapper" /></bean>

spring配置文件2中:配置事务

<!-- 事务管理器 --><bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!-- 数据源 --><property name="dataSource" ref="dataSource" /></bean><!-- 通知 --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!-- 传播行为 --><tx:method name="save*" propagation="REQUIRED" /><tx:method name="insert*" propagation="REQUIRED" /><tx:method name="add*" propagation="REQUIRED" /><tx:method name="create*" propagation="REQUIRED" /><tx:method name="delete*" propagation="REQUIRED" /><tx:method name="update*" propagation="REQUIRED" /><tx:method name="find*" propagation="SUPPORTS" read-only="true" /><tx:method name="select*" propagation="SUPPORTS" read-only="true" /><tx:method name="get*" propagation="SUPPORTS" read-only="true" /></tx:attributes></tx:advice><!-- 切面 --><aop:config><aop:advisor advice-ref="txAdvice"pointcut="execution(* cn.e3mall.sso.service..*.*(..))" /></aop:config>

spring配置文件3中配置redis

<!-- 连接redis单机版 --><bean id="jedisClientPool" class="cn.e3mall.common.jedis.JedisClientPool"><property name="jedisPool" ref="jedisPool"></property></bean><bean id="jedisPool" class="redis.clients.jedis.JedisPool"><!-- 一定要用name,构造方法太多用index容易错 --><constructor-arg name="host" value="192.168.25.128"/><constructor-arg name="port" value="6379"/></bean>

spring配置文件中配置:发布服务,组件扫描,写完服务再给出

web.xml中

<!-- 加载spring容器 --><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/applicationContext*.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>

配置文件db.properties中配置数据库连接

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/e3mall_32?characterEncoding=utf-8
jdbc.username=root
jdbc.password=123456

resource.properties中设置token过期时间

SESSION_EXPIRE=1800

e3-sso-web引入jar包
pom.xml中

<groupId>cn.e3mall</groupId><artifactId>e3-sso-web</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><dependencies><dependency><groupId>cn.e3mall</groupId><artifactId>e3-sso-interface</artifactId><version>0.0.1-SNAPSHOT</version>   </dependency><!-- JSP相关 --><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId></dependency><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><scope>provided</scope></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jsp-api</artifactId><scope>provided</scope></dependency><!-- Spring --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jms</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId></dependency><!-- dubbo相关 --><dependency><groupId>com.alibaba</groupId><artifactId>dubbo</artifactId><exclusions><exclusion><groupId>org.springframework</groupId><artifactId>spring</artifactId></exclusion><exclusion><groupId>org.jboss.netty</groupId><artifactId>netty</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.apache.zookeeper</groupId><artifactId>zookeeper</artifactId></dependency><dependency><groupId>com.github.sgroschupf</groupId><artifactId>zkclient</artifactId></dependency></dependencies><!-- 配置tomcat插件 --><build><plugins><plugin><!-- 配置Tomcat插件 --><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><configuration><path>/</path><!-- 表示访问时候不带工程名的 --><port>8088</port></configuration></plugin></plugins></build>

spring配置文件中除了组件扫描之外还要引用服务,但是Service层还没发布服务,所以待会给出,另外还需要将jsp页面跟静态文件都引入到项目的WEB-INF和webaap下。

web.xml中

<!-- 解决post乱码 --><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>utf-8</param-value></init-param></filter><filter-mapping><filter-name>CharacterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- springmvc的前端控制器 --><servlet><servlet-name>e3-manager</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- contextConfigLocation不是必须的, 如果不配置contextConfigLocation, springmvc的配置文件默认在:WEB-INF/servlet的name+"-servlet.xml" --><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring/springmvc.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>e3-manager</servlet-name><!-- 伪静态化,搜索引擎优化,搜索引擎会先找静态页面 --><url-pattern>/</url-pattern></servlet-mapping>

属性配置文件resource.properties中

TOKEN_KEY=token

功能实现
服务层:e3-sso-service中

  1. 接收参数,判断用户名和密码正确
  2. 用户名和密码都正确的话,生成token,相当于tomcat时候的jsessionId.用uuid生成,保证唯一性。
  3. 将用户信息存入redis。Key为”SESSION”+token,value为查询的用户信息转为的json串。
  4. 设置key的有效期。一般为半个小时
  5. 返回包装了token的E3Result
/** 用户登录处理*/
@Service
public class LoginServiceImpl implements LoginService{@Autowiredprivate TbUserMapper userMapper;@Autowiredprivate JedisClient jedisClient;@Value("${SESSION_EXPIRE}")private Integer SESSION_EXPIRE;public E3Result userLogin(String username, String password) {//1.判断用户名和密码是否正确//根据用户名查询用户信息TbUserExample example = new TbUserExample();Criteria criteria = example.createCriteria();criteria.andUsernameEqualTo(username);List<TbUser> list = userMapper.selectByExample(example);if(list == null || list.size() == 0){//返回登录失败return E3Result.build(400, "用户名或者密码错误");}//取用户信息TbUser user = list.get(0);//判断密码是否正确if(!DigestUtils.md5DigestAsHex(password.getBytes()).equals(user.getPassword())){//2.如果不正确返回登录失败return E3Result.build(400, "用户名或者密码错误");}//3.如果正确生成tokenString token = UUID.randomUUID().toString();//生成的uuid必不重复//4.把用户信息写入redis,key:token,value:用户信息user.setPassword(null);jedisClient.set("SESSION:"+ token, JsonUtils.objectToJson(user));//5.设置Session的过期时间jedisClient.expire("SESSION:"+ token, SESSION_EXPIRE);//6.把token返回return E3Result.ok(token);}
}

注:如果没用过mybatis逆向工程那么花2小时学一下这样看上面的代码更清晰。

E3Result为自定义响应类,如下

public class E3Result implements Serializable{// 定义jackson对象private static final ObjectMapper MAPPER = new ObjectMapper();// 响应业务状态private Integer status;// 响应消息private String msg;// 响应中的数据private Object data;public static E3Result build(Integer status, String msg, Object data) {return new E3Result(status, msg, data);}public static E3Result ok(Object data) {return new E3Result(data);}public static E3Result ok() {return new E3Result(null);}public E3Result() {}public static E3Result build(Integer status, String msg) {return new E3Result(status, msg, null);}public E3Result(Integer status, String msg, Object data) {this.status = status;this.msg = msg;this.data = data;}public E3Result(Object data) {this.status = 200;this.msg = "OK";this.data = data;}get、set方法}

服务写完之后需要发布服务(使用了Dubbo发布服务,Zookeeper作为注册中心)
配置文件4中:组件扫描,发布服务

<context:component-scan base-package="cn.e3mall.sso.service"/><!-- 使用dubbo发布服务 --><!-- 提供方应用信息,用于计算依赖关系 --><dubbo:application name="e3-sso" /><dubbo:registry protocol="zookeeper"address="192.168.25.128:2181" /><!-- 用dubbo协议在20880端口暴露服务 --><dubbo:protocol name="dubbo" port="20883" /><!-- 一个服务对应一个端口 --><!-- 声明需要暴露的服务接口 --><dubbo:service interface="cn.e3mall.sso.service.LoginService" ref="loginServiceImpl" timeout="600000"/><dubbo:service>

然后将e3-sso工程安装到本地仓库

表现层:e3-sso-web中
先要接收服务,spring配置文件中

<!-- 加载配置文件 --><context:property-placeholder location="classpath:conf/resource.properties" /><context:component-scan base-package="cn.e3mall.sso.controller" /><mvc:annotation-driven /><bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/" /><property name="suffix" value=".jsp" /></bean><mvc:resources location="/css/" mapping="/css/**"/><mvc:resources location="/js/" mapping="/js/**"/><mvc:resources location="/images/" mapping="/images/**"/><!-- 引用dubbo服务 --><dubbo:application name="e3-sso-web"/><dubbo:registry protocol="zookeeper" address="192.168.25.128:2181"/>    <dubbo:reference interface="cn.e3mall.sso.service.LoginService" id="loginService" />

处理流程:
1. 传入用户名和密码,调用service层。获取E3Result。
2. 根据status判断登录是否成功
3. 从获得的E3Result中取token信息,存入cookie
4. 返回结果给页面

/** 用户登录处理*/
@Controller
public class LoginController {@Autowiredprivate LoginService loginService;@Value("${TOKEN_KEY}")private String TOKEN_KEY;//TOKEN_KEY=token@RequestMapping("/page/login")public String toLogin(String redirect,Model model){model.addAttribute("redirect", redirect);//返回登录页面return "login";}@RequestMapping(value="/user/login",method=RequestMethod.POST)@ResponseBodypublic E3Result login(String username,String password,HttpServletRequest request,HttpServletResponse response){E3Result result = loginService.userLogin(username, password);//判断是否登录成功if(result.getStatus()==200){String token = (String) result.getData();//如果登录成功,token写入cookie CookieUtils.setCookie(request, response, TOKEN_KEY, token);}return result;}
}

注:cookie一般默认是不能跨域的(商城采用了分布式架构,所以每个模块对应的域名肯定是不一样的,将比如上面的e3-sso端口号是8089,e3-sso-web是8090),但是这里写的Cookie工具类CookieUtils的setCookie()方法中对跨域是进行了处理的。

private static final void doSetCookie(HttpServletRequest request, HttpServletResponse response,String cookieName, String cookieValue, int cookieMaxage, boolean isEncode) {try {if (cookieValue == null) {cookieValue = "";} else if (isEncode) {cookieValue = URLEncoder.encode(cookieValue, "utf-8");}Cookie cookie = new Cookie(cookieName, cookieValue);if (cookieMaxage > 0)cookie.setMaxAge(cookieMaxage);if (null != request) {// 设置域名的cookieString domainName = getDomainName(request);System.out.println(domainName);if (!"localhost".equals(domainName)) {cookie.setDomain(domainName);}}cookie.setPath("/");response.addCookie(cookie);} catch (Exception e) {e.printStackTrace();}}

到这里工程就算做完了。
当用户登录的时候,先进行校验,校验通过后,生成token,作为key,查出来的用户信息作为value存入到redis中并设置key的过期时间。并且将token返回给表现层,表现层将token存入Cookie中。当用户访问其它模块,比如订单模块的时候,我们可以写个拦截器,拦截请求,判断用户是否登录,从Cookie中取token,如果没取到token说明用户根本没登录所以跳转到登录页面,如果取到了token,那么根据token去redis中查询用户信息,说明key已经失效了,跳转到登录页面。否则放行。

比如访问购物车系统(天猫访问购物车要求是登录状态下):
在e3-order-web工程中编写拦截器

/** 用户登录处理*/
public class LoginInterceptor implements HandlerInterceptor {@Autowiredprivate TokenService tokenService;public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {//前处理,执行handler之前执行此方法//返回true:放行  false:拦截//1.从cookie中取tokenString token = CookieUtils.getCookieValue(request, "token");//2.如果没有token,未登录状态if(StringUtils.isBlank(token)){return true;}//3.如果取到token,需要调用sso系统的服务,根据token取用户信息E3Result e3Result = tokenService.getUserByToken(token);if (e3Result.getStatus()!=200){//4.没有取到用户信息,登录已经过期,直接放行return true;}//5.取到用户信息。登录状态。TbUser user = (TbUser) e3Result.getData();//6.把用户信息放到request中,只需要在controller中判断request中是否包含user信息。request.setAttribute("user", user);return true;}public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {//handler执行之后,返回modelAndView之前}public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {//完成处理,返回modelAndView之后(已经响应了)//可以再次处理异常}}

注:这里需要在sso系统中发布一个新的服务

<dubbo:service interface="cn.e3mall.sso.service.TokenService" ref="tokenServiceImpl" timeout="600000"/>

该服务是根据token取用户信息

/** 根据token取用户信息*/
@Service
public class TokenServiceImpl implements TokenService{@Autowiredprivate JedisClient jedisClient;@Value("${SESSION_EXPIRE}")private Integer SESSION_EXPIRE;public E3Result getUserByToken(String token) {//根据token到redis中取用户信息String json = jedisClient.get("SESSION:"+ token);if(StringUtils.isBlank(json)){//取不到信息,登录过期,返回登录过期return E3Result.build(201, "用户登录已经过期");}//取到用户信息,跟新token的过期时间jedisClient.expire("SESSION:"+ token, SESSION_EXPIRE);//返回结果,E3Result其中包含用户对象TbUser user = JsonUtils.jsonToPojo(json, TbUser.class);return E3Result.ok(user); }
}

然后在e3-cart-web工程中引用该服务

    <dubbo:reference interface="cn.e3mall.sso.service.TokenService" id="tokenService" />

测试:

点击登录。提示登录成功后会跳转页面到首页.
查看redis

redis实现单点登录系统相关推荐

  1. SpringBoot+MyBatis+Redis实现SSO单点登录系统(二)

    SpringBoot+MyBatis+Redis实现SSO单点登录系统(二) 三.代码 配置文件配置数据库,redis等相关的信息. # See http://docs.spring.io/sprin ...

  2. SpringBoot+MyBatis+Redis实现SSO单点登录系统(一)

    SpringBoot+MyBatis+Redis实现SSO单点登录系统(一) 一.SSO系统概述 SSO英文全称Single Sign On,单点登录.SSO是在多个应用系统中,用户只需要登录一次就可 ...

  3. 单点登录系统实现基于SpringBoot

    今天的干货有点湿,里面夹杂着我的泪水.可能也只有代码才能让我暂时的平静.通过本章内容你将学到单点登录系统和传统登录系统的区别,单点登录系统设计思路,Spring4 Java配置方式整合HttpClie ...

  4. 我们为何需要单点登录系统

    SSO,Single Sign On,也就是单点登录,保证一个账户在多个系统上实现单一用户的登录 现在随着网站的壮大,很多服务会进行拆分,会做SOA服务,会使用dubbo做微服务,或者简单的小型分布式 ...

  5. sso单点登录系统(解决session共享)

    场景:假设一个用户将自己的登录信息提交到后台,如果session保存的信息分布在多台机器上,并且不共享,那么可能导致用户的登录信息出现短暂的丢失,为什么这样讲,因为用户访问服务器中间还要经过负载均衡服 ...

  6. 互联网分布式微服务云平台规划分析--SSO单点登录系统

    介绍 鸿鹄云架构[SSO单点登录系统]为所有微服务提供统一的用户认证服务,系统本身属于微服务模式,使用JWT+Redis分布式存储方案,确保不同微服务.系统之间的安全通讯和统一用户校验.认证.在整个服 ...

  7. 【SSO】单点登录系统实现

    一.前言 小编在前一篇博客中向大家介绍了使用单点登录的演变过程,最后一步的时候小编向大家展示了分布式架构.其中就用到了单点登录系统.这篇博客继续接上一篇博客,实现一下单点登录系统. 二.环境准备 Ec ...

  8. SSO - 我们为何需要单点登录系统

    SSO,Single Sign On,也就是单点登录,保证一个账户在多个系统上实现单一用户的登录 现在随着网站的壮大,很多服务会进行拆分,会做SOA服务,会使用dubbo做微服务,或者简单的小型分布式 ...

  9. CAS单点登录系统的实现

    CAS单点登录系统的实现 前言 一.CAS思路 二.代码实现 环境准备 代码实现 2.1 MTV系统前端判断是否登录,依据前端cookie是否存在用户信息 2.2 MTV系统前端判断链接是否携带临时票 ...

最新文章

  1. 数据库连接池到底应该设多大?
  2. 代码的演化-DI(理解依赖注入di,控制反转ioc)
  3. 老赖凭本事骗钱,你有本事不被骗吗?
  4. spring java code配置_Spring-09-使用Java的方式配置Spring
  5. Android浏览器速度测试,Android平台浏览器网页加载速度对比评测
  6. Openwrt之移动硬盘ext3/ext4格式化工具
  7. 反欺诈的这几个重点内容值得您关注
  8. 《2018中国AI计算力发展报告》发布!北京算力仅排第二
  9. 10月全球浏览器份额态势:Chrome领先Firefox7.34%
  10. java真题_2017年JAVA考试试题及答案
  11. 关于邮箱显示已经回复,但是已发送邮件里面没有
  12. bugku 旋转跳跃
  13. 天池大数据比赛-菜鸟仓库比赛-第一赛季记录
  14. Excel 2010 SQL应用098 聚合函数之计算某列空值的数目
  15. 易语言MySQL静态编译,我说易语言静态编译太强大……
  16. 3dvary灯光材质为什么不亮_3dmax灯光教程灯光打出来太假?不真实?杂点?曝光?原因都在这儿呢...
  17. Linux安装小企鹅输入法
  18. 【HTTP API】简单的http签名算法
  19. PPT之幻灯片中的大纲选项卡
  20. zebra ZT41142 打印机配置网络连接问题

热门文章

  1. 硕士毕业论文外审要求
  2. 李宏毅深度学习笔记(CNN)
  3. fgets和fputs的使用
  4. 58同城字体加密解密方法
  5. WebRTC Trickle ICE 策略
  6. 图形化编程语言的设计
  7. Java—String类的intern方法的学习
  8. 使用react+redux+react-redux+react-router+axios+scss技术栈从0到1开发一个applist应用
  9. Servlet规范之转发请求
  10. java中year与week year