sso单点登录概念

1.一处登录,处处登录.会单独做一个单点登录系统,只负责颁发token和验证token,和页面登录功能.

2.通过在浏览器cookie中放入token,和在redis中对应token放入用户信息的方式,代替session共享,使用jwt(json web token)自定义一个携带用户信息token加密算法.

3.cookie中的token是已经使用过的token,取名oldToken . url地址栏中的token新颁发的token,取名newToken

做法:

1.首先自定义一个注解,作用在方法上.有3种状态:

1.1 如果为null,表示直接放行,例如商品详情页,用户可以不用登录直接访问.

1.2 如果为false,经常用在购物车方法上,表示可登录可不登录,用户不登录购物车数据保存cookie中,用户登录数据保存数据库并放redis一份.

1.3 如果为true,表示用户必须登录,例如购物车结算跳订单页面.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginRequired {

  boolean isNeededSuccess() default true;

}

2.自定义拦截器,并加入到springr容器中

@Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
  @Autowired
  AuthInterceptor authInterceptor;

  @Override
  public void addInterceptors(InterceptorRegistry registry){
    registry.addInterceptor(authInterceptor).addPathPatterns("/**");
    super.addInterceptors(registry);
  }
}

@Component
public class AuthInterceptor extends HandlerInterceptorAdapter {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HandlerMethod hm = (HandlerMethod)handler; LoginRequired methodAnnotation = hm.getMethodAnnotation(LoginRequired.class); if(methodAnnotation==null){
return true;
}else{
// 先获得用户cookie中关于用户的身份token
//token有四种情况
String token = ""; String oldToken = CookieUtil.getCookieValue(request, "oldToken", true);
if(StringUtils.isNotBlank(oldToken)){
token = oldToken;
}
String newToken = request.getParameter("newToken");
if(StringUtils.isNotBlank(newToken)){
token = newToken;
} if(StringUtils.isNotBlank(token)){
// 验证用户的token是否正确
// 通过远程ws请求认证中心,验证token
String requestUrl = "http://passport.gmall.com:8090/verify?token="+token+"&currentIp="+request.getRemoteAddr();
String successJSON = HttpclientUtil.doGet(requestUrl);
HashMap<String,String> hashMap = new HashMap<>();
HashMap hashMapJSON = JSON.parseObject(successJSON, hashMap.getClass()); if(hashMapJSON!=null&&hashMapJSON.get("success").equals("success")){
// 重新更新cookie的过期时间
CookieUtil.setCookie(request,response,"oldToken",token,60*60,true);
request.setAttribute("memberId",hashMapJSON.get("memberId"));
request.setAttribute("nickname",hashMapJSON.get("nickname"));
return true;
}else{
if(methodAnnotation.isNeededSuccess()){
String ReturnUrl = request.getRequestURL().toString();
response.sendRedirect("http://passport.gmall.com:8090/index?ReturnUrl="+ReturnUrl);
// 拦截验证
return false;
}
}
}else{
if(methodAnnotation.isNeededSuccess()) {
String ReturnUrl = request.getRequestURL().toString();
response.sendRedirect("http://passport.gmall.com:8090/index?ReturnUrl=" + ReturnUrl);
// 拦截验证
return false;
}
}
} return true; }
} 3.单点登录系统代码
@Controller
public class passportController { @Reference
UserService userService; @RequestMapping("vlogin")
public String vlogin(String code, HttpServletRequest request) { // 换取access_token
String access_token_url = "https://api.weibo.com/oauth2/access_token?client_id= 25920146&client_secret=dc8de1392f642a01259b136ff8e970b9&grant_type=authorization_code&redirect_uri=http://passport.gmall.com:8090/vlogin&code=e211655dd6c78a66fcfcfdff552424f6"; Map<String,String> map = new HashMap<String,String>();
map.put("client_id","25920146");
map.put("client_secret","dc8de1392f642a01259b136ff8e970b9");
map.put("grant_type","authorization_code");
map.put("redirect_uri","http://passport.gmall.com:8090/vlogin");
map.put("code",code);
String access_json = HttpclientUtil.doPost("https://api.weibo.com/oauth2/access_token", map);
System.out.println(access_json); Map<String,String> map_access_json = new HashMap<String,String>();
Map access_map = JSON.parseObject(access_json, map_access_json.getClass()); // 获得第三方用户数据
String access_token = (String)access_map.get("access_token");
String uid = (String)access_map.get("uid");// uid uidStr
UmsMember umsMember = new UmsMember();
umsMember = userService.isUidExists(uid); if(umsMember==null){ String show_url = "https://api.weibo.com/2/users/show.json?access_token="+access_token+"&uid="+uid; String user_json = HttpclientUtil.doGet(show_url);
Map<String,String> map_user_json = new HashMap<String,String>();
Map user_map = JSON.parseObject(user_json, map_user_json.getClass());
System.out.println(user_map); // 存入数据库
umsMember.setNickname((String)user_map.get("screen_name"));
umsMember.setUsername((String)user_map.get("name"));
umsMember.setSourceType("2");
umsMember.setSourceUid((String)user_map.get("idstr"));
umsMember.setCreateTime(new Date());
umsMember.setAccessToken(access_token);
umsMember.setAccessCode(code);
umsMember = userService.addUser(umsMember);
} // 根据用户信息生成token
String key = "houruisso";
String ip = request.getRemoteAddr();
Map<String,Object> token_map = new HashMap<>();
token_map.put("nickname",umsMember.getNickname());
token_map.put("memberId",umsMember.getId());
String token = JwtUtil.encode(key, token_map, ip); // 将生成的token和登录用户信息保存在缓存中一分
userService.addUserCache(token,umsMember);
return "redirect:http://search.gmall.com:8083/index?newToken="+token;
} @RequestMapping("login")
@ResponseBody
public String login(UmsMember umsMember, HttpServletRequest request) {
System.out.println("用户登录,验证用户名和密码是否正确"); // 调用用户服务userService,验证用户名和密码
UmsMember umsMemberFromDb = userService.login(umsMember); if (umsMemberFromDb == null) {
return "fail";
} else {
// 根据已经登录的用户信息和,服务器密钥,和其他盐值(根据系统算法)生成一个token
String key = "atguigusso";
String ip = request.getRemoteAddr();
//String ip = request.getHeader("x-forward-for");//nginx
Map<String, Object> map = new HashMap<>();
map.put("nickname", umsMemberFromDb.getNickname());
map.put("memberId", umsMemberFromDb.getId());
String token = JwtUtil.encode(key, map, ip); // 将生成的token和登录用户信息保存在缓存中一分
userService.addUserCache(token,umsMemberFromDb); return token;
} } @RequestMapping("verify")
@ResponseBody
public String verify(String token, String currentIp) {
System.out.println("认证中心认证用户的token"); String key = "houruisso"; String ip = currentIp; Map<String, Object> map = JwtUtil.decode(token, key, ip); Map<String,String> verifyReturn = new HashMap<>();
if (map != null) {
verifyReturn.put("success","success");
verifyReturn.put("memberId",(String)map.get("memberId"));
verifyReturn.put("nickname",(String)map.get("nickname"));
return JSON.toJSONString(verifyReturn);
} else {
verifyReturn.put("success","fail");
return JSON.toJSONString(verifyReturn);
} } @RequestMapping("index")
public String index(String ReturnUrl, ModelMap modelMap) {
System.out.println("认证中心首页"); modelMap.put("ReturnUrl", ReturnUrl);
return "index";
}
}

4.前端代码
<!--底部-->
<input type="text" id="ReturnUrl" th:value="${ReturnUrl}"/><br /> </body>
<script language="JavaScript"> function submitLogin() {
var username = $("#username").val();
var password = $("#password").val();
$.post("login",{username:username,password:password},function(token){
if(token=="fail"){
alert("登录失败,用户名和密码错误");
}else{
window.location.href=$("#ReturnUrl").val()+"?newToken="+token;
}
});
}

@Override
public void addUserCache(String token, UmsMember umsMemberFromDb) {
String tokenKey = "user:"+umsMemberFromDb.getId()+":token";
String userKey = "user:"+umsMemberFromDb.getId()+":info"; Jedis jedis = null; jedis = redisUtil.getJedis(); jedis.setex(tokenKey,60*60,token);
jedis.setex(userKey,60*60, JSON.toJSONString(umsMemberFromDb)); jedis.close();
}

sso单点登录系统的更多相关文章

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

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

  2. sso单点登录系统的压力测试

    环境:vmware centos7.4 2cpu 2核心 工具:ab压力测试工具 测试对象:sso单点登录系统 电脑:win10 4核 项目环境:flask+uwsgi+nginx(uwsgi 2进程 ...

  3. e3mall商城的归纳总结10之freemarker的使用和sso单点登录系统的简介

    敬给读者的话 本节主要讲解freemarker的使用以及sso单点登录系统,两种技术都是比较先进的技术,freemarker是一个模板,主要生成一个静态静态,能更快的响应给用户,提高用户体验. 而ss ...

  4. sso单点登录系统原理与实现

    sso单点登录 1.认识并理解sso及其应用,并能根据其实现原理自行实现sso 没有使用sso单点登录的系统用户再访问同一个系统的不同模块都必须的登录 使用sso单点登录,用户只需要登录一次,并且可以 ...

  5. 统一登录中心SSO 单点登录系统的构想

    什么是单点登录?我想肯定有一部分人“望文生义”的认为单点登录就是一个用户只能在一处登录,其实这是错误的理解.单点登录指的是多个子系统只需要登录一个,其他系统不需要登录了(一个浏览器内).一个子系统退出 ...

  6. 基于cookie的SSO单点登录系统

    利用COOKIE实现单点登录功能 近期公司要求帮一个项目实现单点登录功能,在综合考量下决定采用cookie实现,大概的流程如下图所:

  7. php sso单点登录原理阐述

    原理:就是用户登录了单点登录系统(sso)之后,就可以免登录形式进入相关系统: 实现: 点击登录跳转到SSO登录页面并带上当前应用的callback地址 登录成功后生成COOKIE并将COOKIE传给 ...

  8. Spring Security OAuth2 SSO 单点登录

    基于 Spring Security OAuth2 SSO 单点登录系统 SSO简介 单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自 ...

  9. Java项目接入sso单点登录

    最近在落地cat(java开发的一款开源监控系统)接入公司的内部项目,其中有项需求是接入公司的sso单点登录系统.研究了公司之前java项目接入sso系统,大部分是采用spring框架,然后依赖spr ...

随机推荐

  1. CS184.1X 计算机图形学导论 第3讲L3V1

    二维空间的变换 L3V1这一课主要讲了二维空间的变换,包括平移.错切和旋转. 缩放 缩放矩阵 使用矩阵的乘法来完成缩放 缩放矩阵是一个对角矩阵,对角线上的值对应缩放倍数 错切(shear) 错切可以将 ...

  2. 树莓派(4B)Linux + .Net Core嵌入式-初始化环境(一)

    一.树莓派简单介绍 二.软&件准备 硬件:树莓派4B主机.电源线.TF卡&TF读卡器.PC 软件:win32diskimager(用于烧系统到TF卡).Xshell或Windows T ...

  3. HDU 3371 Connect the Cities(并查集+Kruskal)

    题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=3371 思路: 这道题很明显是一道最小生成树的题目,有点意思的是,它事先已经让几个点联通了.正是因为它先 ...

  4. VAD树结构体的属性以及遍历

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html VAD树的属性以及遍历 前面学习过的PFNDATABSAE是管理物 ...

  5. javascript获取坐标/滚动/宽高/距离

    坐标(鼠标/触摸) event.screenX 鼠标/触摸,相对于显示屏的X坐标 event.screenY 鼠标/触摸,相对于显示屏的Y坐标 event.clientX 鼠标/触摸,相对于浏览器视口 ...

  6. 设计模式(二)Adapter模式

    Adapter模式也被成为Wrapper模式.适配器模式用于填补“现有的程序”和“所需的程序”之间差异的设计模式. Adapter模式有两种,即使用继承的适配器和使用委托的适配器. 1.使用继承的适配 ...

  7. Java基础(二十七)Java IO(4)字符流(Character Stream)

    字符流用于处理字符数据的读取和写入,它以字符为单位. 一.Reader类与Writer类 1.Reader类是所有字符输入流的父类,它定义了操作字符输入流的各种方法. 2.Writer类是所有字符输出 ...

  8. 热门开源网关的性能对比:Goku > Kong > Tyk

    不多说,先展示最后的性能测试结果 我们将Goku与市场上的其他同类热门产品进行比较,使用相同的环境和条件,测试以下产品:Goku.Kong.Tyk.简单介绍下, Goku API Gateway (中 ...

  9. WEB安全的历史

    exp  ===  exploit     漏洞利用代码 中国 黑客发展的 几个阶段  启蒙时代  ,黄金时代 ,黑暗时代 启蒙时代  -- 大致在 20世纪 19年代 中国互联网刚起步  一些青年收 ...

  10. PhpStudy2018后门漏洞预警及漏洞复现&检测和执行POC脚本

    PhpStudy2018后门漏洞预警及漏洞复现&检测和执行POC脚本 phpstudy介绍 Phpstudy是国内的一款免费的PHP调试环境的程序集成包,其通过集成Apache.PHP.MyS ...