文档章节

Shiro集成kisso,搭建单点登录系统

qwzh110
 qwzh110
发布于 2018/02/09 11:22
字数 908
阅读 1492
收藏 47

kisso 是一个中间件,提供 cookie 搭建 java web sso 的组件式解决方案。

shiro是目前比较常用的轻量权限控制框架。

SpringBoot集成Shiro的文章比较多,我不多赘述。下面介绍SpringBoot集成kisso。

思路

  • Spring集成Shiro
  • Shiro托管项目session,使用Redis保存Shiro缓存信息
  • SpringBoot集成kisso
  • kisso单点登录同步shiro授权信息

步骤

1.SpringBoot集成Shiro

略。

2.Shiro托管项目session,使用Redis保存Shiro缓存信息

这个的详细操作过程在这个博文里介绍过了 https://my.oschina.net/qwzhang01/blog/1620339

3.SpringBoot集成kisso

    1)添加配置文件sso.properties

sso.encoding=UTF-8
sso.secretkey=Kisso4SpringBootK80mAS
sso.cookie.name=uid
sso.cookie.domain=canyou.xyz
sso.cookie.maxage=7200
sso.login.url=http://canyou.xyz:8088/login

    2)注入kisso组件


@Configuration
public class WebAppConfig extends WebMvcConfigurerAdapter {

    
    /**
     * 注入kisso拦截器
     *
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new SSOSpringInterceptor()).addPathPatterns("/**").excludePathPatterns("/login/**");
        super.addInterceptors(registry);
    }


    /**
     * 注入Kisso
     *
     * @return
     */
    @Bean(initMethod = "initKisso")
    public WebKissoConfigurer webKissoConfigurer() {
        WebKissoConfigurer webKissoConfigurer = new WebKissoConfigurer("sso.properties");
        return webKissoConfigurer;
    }
}

    3)修改登录方法,登录成功,调用kisso,将登陆信息保存在cookie中

 @RequestMapping(value = "/login/check", method = RequestMethod.POST)
    public String login(@RequestParam(value = "ReturnURL", defaultValue = "") String retuenUrl, LoginUserVo user, RedirectAttributes redirectAttributes, HttpServletRequest request, HttpServletResponse response) {
        if (StrUtil.hasBlank(user.getUsername(), user.getPassword(), user.getSafecode_iput())) {
            redirectAttributes.addFlashAttribute("msg", "用户名或密码验证码都均能为空");
            return "redirect:/login";
        }
        if (!CaptchaKit.validate(user.getSafecode_iput(), request)) {
            redirectAttributes.addFlashAttribute("msg", "验证码错误");
            return "redirect:/login";
        }
        User checkUser = userService.getByUserName(user.getUsername());
        if (checkUser == null) {
            redirectAttributes.addFlashAttribute("msg", "用户不存在,请核对后重新登录");
            return "redirect:/login";
        }
        String encrypt = ShiroCrypt.encrypt(user.getPassword());
        if (!checkUser.getPassword().equals(encrypt)) {
            redirectAttributes.addFlashAttribute("msg", "密码错误,请核对后重新登录");
            return "redirect:/login";
        }

        if (userService.login(checkUser.getUsername(), checkUser.getPassword())) {
            HttpSession session = request.getSession();
            session.setAttribute("username", checkUser.getUsername());
            session.setAttribute("fullName", checkUser.getRealname());
            // 单点登录核心代码
            SSOToken ssoToken = new SSOToken();
            ssoToken.setUid(user.getUsername());
            ssoToken.setApp("oms");
            ssoToken.setIp(IpHelper.getIpAddr(request));
            // 将sessionid保存在kisso的cookie里面
            ssoToken.setData(request.getSession().getId());
            SSOHelper.setSSOCookie(request, response, ssoToken, false);
            return "redirect:/";
        }
        redirectAttributes.addFlashAttribute("msg", "登陆失败");
        return "redirect:/login";
    }

至此,kisso集成完成。符合配置在sso.properties中的domain的域名cookie中,都会同步登陆信息。

但是目前只是把登陆信息同步在kisso里面了,对于shiro来说,不同应用之间的认证、授权信息并没有同步,因此需要在所有系统里面根据kisso,添加shiro的认证授权信息。

4.kisso单点登录同步shiro授权信息

上面已经实现了应用session由shiro托管,shiro缓存实现共享。给shiro添加filter,通过filter,对于符合kisso的单点登录条件的应用,通过kisso获取原来已经登录项目的sessionid,将其写入新应用的cookie里面,即实现将原已经授权认证的项目的shiro信息同步至新项目中。


import cn.hutool.core.util.StrUtil;
import com.baomidou.kisso.SSOHelper;
import com.baomidou.kisso.SSOToken;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.springframework.stereotype.Component;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class KissoFilter extends AccessControlFilter {

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String username = (String) httpServletRequest.getSession().getAttribute("username");
        return StrUtil.isNotBlank(username);
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        SSOToken ssoToken = SSOHelper.getToken((HttpServletRequest) request);
        if (ssoToken != null && ssoToken.getApp().equals("oms")) {
            Cookie cookie = new Cookie("csid", ssoToken.getData());
            cookie.setPath("/");
            ((HttpServletResponse) response).addCookie(cookie);
        }
        return true;
    }
}

把filter注册为shiro的过滤器,过滤所有请求

@Bean
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, Filter> filterMap = new HashMap<>();
        filterMap.put("authc_kisso", new KissoFilter());
        filterMap.put("shiro_kisso", new KiSsoShiroAuthFilter());
        filterMap.put("logout_kisso", new KiSsoShiroLogoutFilter());
        shiroFilterFactoryBean.setFilters(filterMap);
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();        
        filterChainDefinitionMap.put("/js/**", "anon");
        filterChainDefinitionMap.put("/css/**", "anon");
        filterChainDefinitionMap.put("/fonts/**", "anon");
        filterChainDefinitionMap.put("/login/logout", "logout_kisso");
        filterChainDefinitionMap.put("/login/**", "anon");       
        filterChainDefinitionMap.put("/**", "authc_kisso, shiro_kisso");       
        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setSuccessUrl("/index");       
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

传送门

© 著作权归作者所有

共有 人打赏支持
qwzh110
粉丝 11
博文 3
码字总数 3126
作品 0
深圳
程序员
私信 提问
加载中

评论(7)

f
fruggy
你好,不需要再单独引入sso.properties了
j
joydon

引用来自“BoXuan”的评论

请问现在不都流行Json web token吗?用kisso做单点登录的好处是什么?

引用来自“张奇文”的评论

这个是后端系统,没有做前后端分离,分模块以后需要单点登录的情况下使用的。😄
写的不错就是用了BEETL 如果把beetl去掉 你这项目可以打99分。但是有beetl对不起了 顶多65分
ht896632
ht896632

引用来自“会飞的小强”的评论

请问一下,如果用shiro统一管理用户和权限,不就支持sso吗,而且session也是统一管理在redis中?为什么还要引用kisso?

引用来自“张奇文”的评论

感谢这个问题,确实如您所说,session共享以后,对于多模块,可以在shiro的sessionManager的里面设置cookie的domain,sessionIdCookie.setDomain(".canyou.xyz");这样扩大了cookie的范围,又因为session共享在redis里面,不需要kisso就可以实现单点登录。但是在查资料的时候没有看到有人这么用,做项目的时候没敢用,所以还是加了kisso中间件。😄
我就是redis共享的
qwzh110
qwzh110

引用来自“会飞的小强”的评论

请问一下,如果用shiro统一管理用户和权限,不就支持sso吗,而且session也是统一管理在redis中?为什么还要引用kisso?
感谢这个问题,确实如您所说,session共享以后,对于多模块,可以在shiro的sessionManager的里面设置cookie的domain,sessionIdCookie.setDomain(".canyou.xyz");这样扩大了cookie的范围,又因为session共享在redis里面,不需要kisso就可以实现单点登录。但是在查资料的时候没有看到有人这么用,做项目的时候没敢用,所以还是加了kisso中间件。😄
qwzh110
qwzh110

引用来自“BoXuan”的评论

请问现在不都流行Json web token吗?用kisso做单点登录的好处是什么?
这个是后端系统,没有做前后端分离,分模块以后需要单点登录的情况下使用的。😄
银杏卡卡
银杏卡卡
请问现在不都流行Json web token吗?用kisso做单点登录的好处是什么?
会飞的小强
请问一下,如果用shiro统一管理用户和权限,不就支持sso吗,而且session也是统一管理在redis中?为什么还要引用kisso?
基于 Cookie 的 SSO 中间件 - kisso

kisso = cookie sso 基于 Cookie 的 SSO 中间件,它是一把快速开发 java Web 登录系统(SSO)的瑞士军刀。欢迎大家使用 kisso !! kisso 帮助文档下载 1、支持单点登录 2、支持登录Cookie缓存...

青苗
2014/06/18
0
21
JFinal 集成kisso怎么使用里面的shiro

@青苗 你好,想跟你请教个问题:现在是这样子的,我用kisso做单点登录,要用到shiro,看kisso也封装了shiro的支持,但在Jfinal下不知道怎么使用。

创客168
2017/03/05
855
1
kisso 3.6 发布,新增文档、集成 shiro

kisso = cookie sso 基于 Cookie 的 SSO 中间件,它是一把快速开发 java Web 登录系统(SSO)的瑞士军刀。 kisso 帮助文档下载 kisso 依赖 jars kisso_oauth2 演示 demo kisso_ApiServer 移动...

青苗
2016/03/01
2.9K
4
JEECG 集成KiSSO单点登录实现统一身份认证

JEECG 集成KiSSO单点登录实现统一身份认证 JEECG 如何为其他第三方系统实现统一身份认证服务,实现单点登录? 第三方系统如何对接呢? 今天为大家揭开这层面纱,让大家了解实质,使用它更快速...

Jeecg
2018/11/29
0
0
轻量级开源博客框架--Zblog4java

zblog4java zblog的java模仿版,zblog4java轻量级开源博客框架,集成spring mvc+kisso+mybatis-plus 设计: 整体架构使用spring mvc框架 权限层使用 kisso (集成shiro,单点登录等) 持久层使...

angryid
2016/10/14
3.4K
4

没有更多内容

加载失败,请刷新页面

加载更多

java框架学习日志-13(Mybatis基本概念和简单的例子)

在mybatis初次学习Mybatis的时候,遇到了很多问题,虽然阿里云的视频有教学,但是视频教学所使用的软件和我自己使用的软件不用,我自己用的数据库是oracle数据库,开发环境是idea。而且视频中...

白话
今天
3
0
Java基础:String、StringBuffer和StringBuilder的区别

1 String String:字符串常量,字符串长度不可变。Java中String是immutable(不可变)的。 String类的包含如下定义: /** The value is used for character storage. */private final cha...

watermelon11
今天
2
0
mogodb服务

部署MongoDB 官网: https://www.mongodb.com/download-center/community 创建mongo数据目录 mkdir /data/mongodb 二进制部署 wget -c https://fastdl.mongodb.org/linux/mongodb-linux-x8......

以谁为师
昨天
5
0
大神教你Debian GNU/Linux 9.7 “Stretch” Live和安装镜像开放下载

Debian项目团队于昨天发布了Debian GNU/Linux 9 "Stretch" 的第7个维护版本更新,重点修复了APT软件管理器中存在的安全漏洞。在敦促每位用户尽快升级系统的同时,Debian团队还发布了Debian ...

linux-tao
昨天
4
0
PHP 相关配置

1. php-fpm的pool 编辑php-fpm配置文件php-fpm.con vim /usr/local/php/etc/php-fpm.conf //在[global]部分增加以下内容 include = etc/php-fpm.d/*.conf # 相当与Nginx的虚拟主机文件 “vho......

Yue_Chen
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部