方式一 多次登录方式

  1. MVC Controller 的 sso 方法
@RequestMapping(value = "ssoLogin.do")
public String sso(String userName, String password,HttpServletRequest request, HttpServletResponse response) {AuthUser user = userDao.getUserByname(userName);UsernamePasswordToken token = new UsernamePasswordToken(username, password);//获取当前的SubjectSubject currentUser = SecurityUtils.getSubject();currentUser.login(token);currentUser.getSession("true").setAttribute("userName",userName);//shrio sessioncurrentUser.getSession().setAttribute("loginName",userName);//http sessionreturn "xxx"; //页面
}
  1. 调用
String path = "osdp";//request.getContextPath();//项目地址
String basePath = request.getScheme() + ":" +  request.getServerName() + ":" +  request.getServerPort() + path;//url
String userName = UserHolder.getUserName();
String password =  UserHolder.getPassword();
String data = "userName="  + userName + "&password="  + password;
return "redirect:" +  basePath + "/ssoLogin" + "?" + data;

方式二 自定义Token令牌

  1. MVC Controller 映射 sso 方法
  /*** 单点登录(如已经登录,则直接跳转)* @param userCode 登录用户编码* @param token 登录令牌,令牌组成:sso密钥+用户名+日期,进行md5加密,举例:* String secretKey = Global.getConfig("shiro.sso.secretKey");* String token = Digests.md5(secretKey + userCode + DateUtils.getDate("yyyyMMdd"));* @param url 登录成功后跳转的url地址。* @param relogin 是否重新登录,需要重新登录传递true* 例如:http://localhost/project/sso/{token}?url=xxx&relogin=true*/
@RequestMapping(value = "sso/{userCode}/{token}")
public String sso(@PathVariable String userCode, @PathVariable String token,@RequestParam(required=true) String url, String relogin, Model model) {Principal principal = SecurityUtils.getSubject().getPrincipal();// 如果已经登录if(principal != null){// 如果设置强制重新登录,则重新登录if (BooleanUtils.toBoolean(relogin)){SecurityUtils.getSubject().logout();}// 否则,直接跳转到目标页else{return "redirect:" + Encodes.urlDecode2(url);}}// 进行单点登录if (token != null){UsernamePasswordToken upt = new UsernamePasswordToken();try {upt.setUsername(userCode); // 登录用户名upt.setPassword(token.toCharArray()); // 密码组成:sso密钥+用户名+日期,进行md5加密,举例: Digests.md5(secretKey+username+20150101))upt.setParams(upt.toString()); // 单点登录识别参数,see: AuthorizingRealm.assertCredentialsMatch} catch (Exception ex){if (!ex.getMessage().startsWith("msg:")){ex = new AuthenticationException("msg:授权令牌错误,请联系管理员。");}model.addAttribute("exception", ex);}try {SecurityUtils.getSubject().login(upt);return "redirect:" + Encodes.urlDecode2(url);} catch (AuthenticationException ae) {if (!ae.getMessage().startsWith("msg:")){ae = new AuthenticationException("msg:授权错误,请检查用户配置,若不能解决,请联系管理员。");}model.addAttribute("exception", ae);}}return "error/403";
}
  1. 重载org.apache.shiro.realm.AuthorizingRealm类的assertCredentialsMatch方法
/**
* 认证密码匹配调用方法
*/
@Override
protected void assertCredentialsMatch(AuthenticationToken authcToken,AuthenticationInfo info) throws AuthenticationException {UsernamePasswordToken token = (UsernamePasswordToken) authcToken;// 若单点登录,则使用单点登录授权方法。if (token.toString().equals(token.getParams())){// sso密钥+用户名+日期,进行md5加密,举例: Digests.md5(secretKey+username+20150101))String secretKey = Global.getConfig("shiro.sso.secretKey");String password = Digests.md5(secretKey + token.getUsername() + DateUtils.getDate("yyyyMMdd"));if (password.equals(String.valueOf(token.getPassword()))){return;}}super.assertCredentialsMatch(token, info);
}
  1. 实现Shiro无状态访问,如通过传递sessionid参数即可实现会话访问
public class SessionManager extends DefaultWebSessionManager {public SessionManager() {super();}@Overrideprotected Serializable getSessionId(ServletRequest request, ServletResponse response) {// 如果参数中包含“__sid”参数,则使用此sid会话。 例如:http://localhost/project?__sid=xxx&__cookie=true// 其实这里还可以使用如下参数:cookie中的session名称:如:JSESSIONID=xxx,路径中的 ;JESSIONID=xxx,但建议还是使用 __sid参数。String sid = request.getParameter("__sid");if (StringUtils.isNotBlank(sid)) {// 是否将sid保存到cookie,浏览器模式下使用此参数。if (WebUtils.isTrue(request, "__cookie")){HttpServletRequest rq = (HttpServletRequest)request;HttpServletResponse rs = (HttpServletResponse)response;Cookie template = getSessionIdCookie();Cookie cookie = new SimpleCookie(template);cookie.setValue(sid); cookie.saveTo(rq, rs);}// 设置当前session状态request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,ShiroHttpServletRequest.URL_SESSION_ID_SOURCE); // session来源与urlrequest.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sid);request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);return sid;}else{return super.getSessionId(request, response);}}
}
  1. 调用
String path = "osdp";//request.getContextPath();//项目地址
String basePath = request.getScheme() + ":" +  request.getServerName() + ":" +  request.getServerPort() + path;//url
String userName = UserHolder.getUserName();
String secretKey = "SSO";
String token =   DigestUtils.md5Hex(secretKey + userName + CommonUtil.getToday());
String data = "userName="  + userName + "&token="  + token;
return "redirect:" +  basePath + "/ssoLogin" + "?" + data;

注意:shiro配置放开单点请求:/sso** =anon

以上两种方式可以实现简单的单点登录,基本思想就是多个子系统登录一遍(自定义token登录或用户名密码登录,原理一样)。

多点注销

每一个子项目注销一遍:

final String loginName = session.getAttribute("loginName");//当前登录帐号new Thread(new Runnable(){@Overridepublic void run(){HttpUtil.get("xxx/ssoLogout?loginName=" + loginName);//接口调用:注销其他项目}
}).start();
//注销
SecurityUtils.getSubject().logout();void ssoLogout(HttpServletRequest request, HttpServletResponse response){String loginName = request.getParameter("loginName"); //注销帐号// 1.获取当前用户sessionIdString currentUserSessionId = SecurityUtils.getSubject().getSession().getId().toString();// 2.获取shiro的sessionManagerDefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();DefaultWebSessionManager sessionManager = (DefaultWebSessionManager)securityManager.getSessionManager();// 3.获取所有已登录用户的session列表Collection<Session> sessions = sessionManager.getSessionDAO().getActiveSessions();//清除sessionif(!CollectionUtils.isEmpty(sessions)&&sessions.size() > 1){User user = null;for(Session session:sessions){// 4. 获取已登录用户的session的key值SimplePrincipalCollection simplePrincipalCollection = (SimplePrincipalCollection) session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);// 5. 获取new SimpleAuthenticationInfo(user, pwd, this.getName())中放进去的第一个参数user = (User) simplePrincipalCollection.getPrimaryPrincipal();// 6. 清除当前用户及以前登录时保存的session会话if (loginName.equals(user.getUserName()) && session.getId().equals(currentUserSessionId)) {sessionManager.getSessionDAO().delete(session);System.out.println("清理用户["+loginName+"],SessionId为["+session.getId()+"]的Session信息!");}}}
}

单点登录多点注销shiro的简单实现相关推荐

  1. 单点登录cas-4.0.0 只是简单的同时登入,同时登出功能

    什么是单点登录 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统 ...

  2. 单点登录、注销实现原理(SSO)

    SSO实现原理 简介 一.SSO登录原理: 设计案例 二.SSO注销原理: 1.设计案列 总结 简介 单点登录是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统的保护资源,若用户在 ...

  3. 单点登录原理和java实现简单的单点登录

    摘要:单点登录(SSO)的技术被越来越广泛地运用到各个领域的软件系统当中.本文从业务的角度分析了单点登录的需求和应用领域:从技术本身的角度分析了单点登录技术的内部机制和实现手段,并且给出Web-SSO ...

  4. Shiro CAS 实现单点登录

    1.简介 CAS:Yale 大学发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法. Shiro:Apache Shiro是一个Java安全框架,可以帮助我们完成认证.授权.会话管 ...

  5. 简易的单点登录系统代码实现

    本文是对单点登录系统的一个简易代码实现,具体原理见 单点登录原理与简单实现 (可点击). 代码只涉及最基础的单点登录与注销.不涉及角色.权限.加密等.因为如果我们系统真要使用单点登录的话,应该不会自己 ...

  6. OAuth 2 实现单点登录,通俗易懂!

    [文章来源]https://sourl.cn/hMw7yT 单点登录是多域名企业站点流行的登录方式.本文以现实生活场景辅助理解,力争彻底理清 OAuth2.0 实现单点登录的原理流程.同时总结了权限控 ...

  7. 图文剖析:单点登录常见解决方案实现原理

    作者:一叶知秋 https://muyinchen.github.io/ 一.共享Session 二.基于OpenId的单点登录 三.基于Cookie的OpenId存储方案 四.B/S多域名环境下的单 ...

  8. 通用权限管理系统组件 中集成多个子系统的单点登录(网站入口方式)附源码

    通用权限管理系统组件 (GPM - General Permissions Manager) 中集成多个子系统的单点登录(网站入口方式)附源码 上文中实现了直接连接数据库的方式,通过配置文件,自定义的 ...

  9. 死磕单点登录的实现原理

    单点登录在现在的系统架构中广泛存在,他将多个子系统的认证体系打通,实现了一个入口多处使用,而在架构单点登录时,也会遇到一些小问题,在不同的应用环境中可以采用不同的单点登录实现方案来满足需求.我将以我所 ...

最新文章

  1. 随机森林(Random Forest)和梯度提升树(GBDT)有什么区别?
  2. 【零基础入门数据挖掘】-数据分析
  3. 浅谈C++函数的参数
  4. 深度学习基础(一)起源
  5. Kogito,ergo规则—第2部分:规则的全面执行模型
  6. Java类的加载过程,类加载器,双亲委派原则
  7. 20-190-092-安装-Flink集群安装 flink-1.9.0 On Yarn
  8. 高甜预警|甜齁你的情人节促销海报设计模板
  9. Spring的注入方式详解
  10. Linux 的 top 命令平均负载
  11. SQLite学习笔记
  12. 怎么做QQ、微信等消息气泡
  13. Java实现进制转换方法汇总
  14. python3.8.2 安装 win7下安装
  15. mysql加载audit失败_MySQL5.5 安装mcafee mysql-audit插件 不成功
  16. 最大子矩阵和POJ1050
  17. 马悦凌:从初级护士到“民间奇医”[2]
  18. PHP开发小技巧①⑥—提取富文本字符串中的文本内容
  19. Win7怎么安装?推荐3种Windows7安装方法
  20. 智能合约安全(一):以太坊机制及安全问题

热门文章

  1. 位图(bitmap)—— C语言实现
  2. Java 基础 —— 注解
  3. MinGW —— Minimalist GNU for Windows、Cygwin —— Windows 下的类 unix 系统
  4. keras + tensorflow 基本使用 —— backend
  5. 力学 —— 圆周运动
  6. 由递推关系到通项公式
  7. STL 中的容器们 (二)
  8. numpy 常用工具函数 —— np.bincount/np.average
  9. python 北上资金_如何查看北向资金? 什么是北向资金 在股市里面,南代表的是HK,北代表的是大陆。北向 = 从南向北流动,那么北向资金就很好理解了,就是HK的... - 雪球...
  10. 自学python买什么书比较好-python官方推荐30本面向初学者的书籍!你看过几本?...