当我们的网站采用分布式部署系统时,每个子系统拥有自己独立的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. mfc CListCtrl

    了解CListCtrl属性 了解CListCtrl常用成员函数 代码示例 一.CListCtrl常用属性 View:视图方式;.大(标准)图标2.小图标3.列表4.报表 Sort:排序; No Scr ...

  2. SQLAlchemy 关联表删除实验

    本实验所用代码来源于官网文档 from sqlalchemy import Table, Column, Integer, String, ForeignKey from sqlalchemy.orm ...

  3. OLEDB数据源和目标组件

    在SSIS工程的开发过程中,OLEDB 数据源和目标组件是最常用的数据流组件.从功能上讲,OLEDB 数据源组件用于从OLEDB 提供者(Provider)中获取数据,传递给下游组件,OLEDB提供者 ...

  4. 基于HTTPS的中间人攻击-BaseProxy

    前言 在上一篇文章BaseProxy:异步http/https代理中,我介绍了自己的开源项目BaseProxy,这个项目的初衷其实是为了渗透测试,抓包改包.在知识星球中,有很多朋友问我这个项目的原理及 ...

  5. Phabricator 在 centos 系统下发送 Email的配置

    前言 phabricator 配置email 其实很简单,配好smtp 服务器.端口.协议.用户名和登陆密码,但过程却好麻烦. 开始时跟着官网配 sendmail ,又 google 又 baidu, ...

  6. Asp.Net_的传值跟存储值操作

    页面传值是学习asp.net初期都会面临的一个问题,总的来说有页面传值.存储对象传值.ajax.类.model.表单等.但是一般来说,常用的较简单有QueryString,Session,Cookie ...

  7. 高精度加法--C++

    高精度加法--C++ 仿照竖式加法,在第一步计算的时候将进位保留,第一步计算完再处理进位.(见代码注释) 和乘法是类似的. #include <iostream> #include < ...

  8. PAT甲题题解-1040. Longest Symmetric String (25)-求最长回文子串

    博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6789177.html特别不喜欢那些随便转载别人的原创文章又不给 ...

  9. 每日Scrum(8)

    今天:在程序中嵌入剖面图,进行美化 明天:测试分析,找学弟学妹来体验我们的软件 任务看板: 燃尽图:

  10. 基于SSH框架的网上书店系统开发的质量属性

    基于SSH框架的网上书店系统开发的质量属性 对于我的基于SSH框架的网上书店系统的开发要实现的质量属性有可用性.可修改性.性能.安全性.易用性和可测试性. 1.对于可用性方面的战术: 可用性(Avai ...