当我们的网站采用分布式部署系统时,每个子系统拥有自己独立的session,如果不实现session共享,当用户切换系统访问的时候,会不停的提示登录,这对于用户体验是非常不好的。因此对于多个子系统的的访问,为了达到用户登录一次即可以访问其他各个子系统,我们采用了sso单点登录系统。之前文章介绍了单点登录系统的实现功能1,现在我们来看下当访问子系统时如何拦截用户,当用户的session过期了,如何提示用户登录,这里采用了SpringMVC的拦截器的实现。

(1)当登录页面时,用户登录成功后,在页面的首页可以显示:某某,欢迎您访问此网站。这时候我们是将之前生成的用户的token值写入Cookie中,因为只要浏览器没关,cookie就存在,当不设置cookie的过期时间时,浏览器关闭,cookie就消逝。将token的内容写入cookie,然后我们利用jsonp访问sso系统的利用token读取用户信息。然后显示在页面即可。

  另外这里还用到一个技术:就是分布式系统的cookie的共享问题。这个将cookie的属性domain设置成全局共享即可。即不同的子系统的域名是不同的,sso.taotao.com;search.taotao.com;我们需要将其域名设置为**.taotao.com,这样可以实现cookie的共享。

具体实现如下:

   if (null != request) {// 设置域名的cookie
String domainName = getDomainName(request);
System.out.println(domainName);
if (!"localhost".equals(domainName)) {
cookie.setDomain(domainName);
}
}
cookie.setPath("/");
response.addCookie(cookie);
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 得到cookie的域名
*/
private static final String getDomainName(HttpServletRequest request) {
String domainName = null; String serverName = request.getRequestURL().toString();
if (serverName == null || serverName.equals("")) {
domainName = "";
} else {
serverName = serverName.toLowerCase();
serverName = serverName.substring(7);
final int end = serverName.indexOf("/");
serverName = serverName.substring(0, end);
final String[] domains = serverName.split("\\.");
int len = domains.length;
if (len > 3) {
// www.xxx.com.cn
domainName = "." + domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
} else if (len <= 3 && len > 1) {
// xxx.com or xxx.cn
domainName = "." + domains[len - 2] + "." + domains[len - 1];
} else {
domainName = serverName;
}
} if (domainName != null && domainName.indexOf(":") > 0) {
String[] ary = domainName.split("\\:");
domainName = ary[0];
}
return domainName;
}

  (2)当用户访问订单系统的时候,如果用户没有登录,这时候需要拦截用户提示用户登录此系统。这时候用了拦截器的作用。

package com.taotao.portal.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView; import com.taotao.common.utils.CookieUtils;
import com.taotao.pojo.TbUser;
import com.taotao.portal.service.impl.UserServiceImpl; public class LoginInterceptor implements HandlerInterceptor {
@Autowired
private UserServiceImpl userService; //执行之前拦截
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
/* handler执行之前拦截,根据true或者false来判断是否拦截。
浏览器没关,这个cookie就存在,也就说token在里面,至于token的session是否有效,这个需要再判断。
当用户登录子系统时,需要提示用户进行登录,这是好用到拦截器,拦截这个页面,原理的具体实现是这样的
第一步:当用户访问页面时,判断cookie中是否有该用户的token。即先从cookie中获取token对象。
* 第二步:根据token查询用户是否存在,调用sso的从token中查询用户的接口来查询用户(这个过程是先从redis中检查token是否过期,如果过期则没有用户,需要登录,如果没有过期,则表示存在用户,因为之前用户信息写入了redis)
*通过查询用户,如果用户存在,则放行,如果不存在,则进行拦截,则跳转到sso的登录系统,提示登录
*/
String token = CookieUtils.getCookieValue(request,"TT_TOKEN");
//根据token来获取用户的信息,调用sso接口
TbUser user= userService.getBySSO(token);
//判断用户是否存在
if (user==null) {
//如果用户为空,则拦截到登录界面,页面重定向到的登录页面
response.sendRedirect(userService.SSO_BASE_URL+userService.SSO_PAGE_LOGIN+"?redirect="+request.getRequestURL());
//response.sendRedirect(userService.SSO_BASE_URL + userService.SSO_PAGE_LOGIN + "?redirect=" + request.getRequestURL());
return false;
} return true;
}
//之后拦截
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// handler执行之后拦截 } @Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub } }

  调用sso根据token获取用户信息

package com.taotao.portal.service.impl;

import org.springframework.beans.factory.annotation.Value;

import com.taotao.common.utils.HttpClientUtil;
import com.taotao.common.utils.JsonUtils;
import com.taotao.common.utils.TaotaoResult;
import com.taotao.pojo.TbUser;
import com.taotao.portal.service.UserService;
//通过token来获取用户信息,需要调用sso的接口信息
public class UserServiceImpl implements UserService {
@Value("${SSO_BASE_URL}")
public String SSO_BASE_URL;
@Value("${SSO_TOKEN_URL}")
public String SSO_TOKEN_URL;
@Value("${SSO_PAGE_LOGIN}")
public String SSO_PAGE_LOGIN; //这是根据token获取用户信息 @Override
public TbUser getBySSO(String token) {
//不同子系统之间的访问,跨域访问,利用httpclient来实现
String json = HttpClientUtil.doGet(SSO_BASE_URL+SSO_TOKEN_URL+token);
TaotaoResult result=TaotaoResult.formatToPojo(json, TbUser.class);
if (result!=null) {
TbUser user=(TbUser) result.getData();
return user;
}
return null;
} }

  最后不要忘了重要的一步:在springMVC中配置拦截器。这个配置就关系到到了哪个功能模块,使用拦截器,比如我们提交订单的时候,如果用户没有登录,则此处增加拦截器。因为拦截器是在我们商城的大的一个客户端,淘淘商城中相当于taotao-portal中,当我们写好了订单服务的接口时,url是order/***,用httpclientUtil来调用订单服务的接口,此时我们在springMVC.xml配置文件中,设置拦截order,如果提交订单时如果没有登录就会跳转到登录窗口。

只需要将这里的

在springMVC中配置拦截器:

分布式系统登录功能拦截器的实现以及cookie的共享问题(利用cookie实现session在分布式系统的共享)的更多相关文章

  1. SpringBoot整合Mybatis完整详细版二:注册、登录、拦截器配置

    接着上个章节来,上章节搭建好框架,并且测试也在页面取到数据.接下来实现web端,实现前后端交互,在前台进行注册登录以及后端拦截器配置.实现简单的未登录拦截跳转到登录页面 上一节传送门:SpringBo ...

  2. SpringBoot日记——登录与拦截器篇

    之前的文章我们把登录页写了出来,但是想要让登录现实他的基本功能,要如何做呢?本篇文章就来帮你实现第一步,让登录页对账号密码做校验,并且完成登录跳转. LoginController 1. 要实现登录, ...

  3. taotao用户登录springMVC拦截器的实现

    在springMVC中写拦截器,只需要两步: 一.写 java 拦截器类,实现 interceptor 拦截器接口. 二.在 springMVC 的xml配置文件中,配置我们创建的拦截器对象及其拦截目 ...

  4. 【struts2】自定义登录检查拦截器

    在实际开发中,一个常见的功能要求是:有很多操作都需要登录后才能操作,如果操作的时候还没有登录,那么通常情况下会要求跳转回到登录页面. 1)如何实现这样的功能呢? 在具体实现之前,先来考虑几个问题: ( ...

  5. spring登录验证拦截器和根据用户角色登录

    大家都知道spring的用户登录拦截器,确实省去了程序员不少的精力,下面说说我在项目中使用的感受. 德安微信管理后台是管理多个微信帐号的平台,登录到平台的用户有三个角色,游客和微信帐号管理员.超级管理 ...

  6. 案例47-crm练习登录校验拦截器

    1 LoginInterceptor package www.test.web.interceptor; import java.util.Map; import com.opensymphony.x ...

  7. 基于Springmvc的登录权限拦截器

    1.什么是拦截器 拦截器是指通过统一拦截从浏览器发往服务端的请求来完成功能的增强. 使用场景:解决请求的共性问题(如:乱码问题,权限验证问题等) 2.拦截器的基本工作原理 springmvc可以通过配 ...

  8. 4_4.springboot之Web开发登录和拦截器

    1.登录处理 1).禁用模板引擎的缓存 # 禁用缓存 spring.thymeleaf.cache=false 2).页面修改完用ctrl+f9:重新编译: LoginController @Cont ...

  9. SpringMVC拦截器(实现登录验证拦截器)

    本例实现登陆时的验证拦截,采用SpringMVC拦截器来实现 当用户点击到网站主页时要进行拦截,用户登录了才能进入网站主页,否则进入登陆页面 核心代码 首先是index.jsp,显示链接 <%@ ...

随机推荐

  1. 关于Trie的一些算法

    最近学习了一下关于Trie的一些姿势,感觉很实用. 终于不用每次看到字符串判重等操作就只想到hash了 关于Trie的定义,来自百度百科 在计算机科学中,Trie,又称前缀树或字典树,是一种有序树状的 ...

  2. 【php增删改查实例】第八节 - 部门管理模块(编写PHP程序)

    首先,在同级目录新建一个query.php文件: 接着,去刷新页面,打开F12,NetWork,看看当前的请求能不能走到对应的php文件? 这就说明datagrid确实能够访问到query.php 只 ...

  3. ubuntu下安装搜狗输入法

    1.如果系统中未安装依赖fcitx,libssh2-1,或者依赖fcitx,libssh2-1的版本低的话,则需提前安装或者升级,否则安装输入法时会出错 安装命令 sudo apt-get insta ...

  4. 微信小程序之地理位置授权 wx.getLocation

    1. 授权地理位置 点击按钮,弹出授权弹窗,点击允许后,在以后的操作中可以随时获取到用户地理位置 点击拒绝后,将无法获取到地理位置,也无法再次点击弹出弹窗. <button bindtap='o ...

  5. [UOJ#461]新年的Dog划分[二分图染色、二分]

    题意 给你一张无向连通图,你并不知道有哪些边,你首先要回答这张图是否是二分图,如果是,回答这张图黑白染色过后的任意一个点集.你需要在2000次询问内找到结果,每次你可以询问原图中一个边集删掉后是否还连 ...

  6. Js_特效II

    字号缩放 让文字大点,让更多的用户看的更清楚.(也可以把字体变为百分比来实现)<script type="text/javascript">  function doZ ...

  7. Git的简单操作

    一.Git安装 windows下,可在在git官网下载(https://git-scm.com/downloads) 也有360提供的git(http://baoku.360.cn/soft/show ...

  8. 博客目录 Blog directory

    Linux 学习笔记 Linux/Mac 挂载远程服务器目录到本地 --Mount remote server directory to local PC 远程连接服务器端Jupyter Notebo ...

  9. Delphi中 弹出框的用法

    Delphi中的提示框有 Application.MessageBox  ShowMessage messagedlg 个人认为 相对来说 Application.MessageBox 更加灵活 也相 ...

  10. Week11分数