告别shiro-cas单点登录集成库,这款简单且强壮的Java Web安全引擎pac4j你值得拥有

简介: 告别shiro-cas单点登录集成库,这款简单且强壮的Java Web安全引擎pac4j你值得拥有

pac4j官网地址传送门。


pac4j引擎全称为powerful authentication client for java,这是笔者根据其官网介绍推测的全称,不一定正确,姑且这样叫着。


一、缘何遇到该引擎


笔者在集成CAS单点登录服务时使用springboot+shiro搭配shiro-cas库,但是总是遇到非法令牌的问题即invalid_ticket,找了各种解释。


1.CAS服务器令牌失效时间短的问题

笔者更改配置文件,尝试多次,貌似不起作用,官方说的这是默认且唯一的配置;

2.缺少其它依赖库

引入后也不得行;

3.客户端应用路径问题

Url缺少“/”


总之成功的都是相似的,不成功的原因千奇百怪。


更要命的是说,该库在退出的时候也有bug,折腾了许久,未果。


就在GitHub上搜springboot shiro cas,就出来了使用pac4j引擎的项目,而且是一个很简单的纯测试项目。项目地址传送门

1666264617425.jpg

下载跑起来测试一下,很舒服,直接成功。 😃

1666264725838.jpg


二、引擎能力


先来看一下这个安全引擎能够支持的框架,如下图,几乎包揽市面上的所有的框架,当然Shiro和Spring Security也在其中。在对接的时候引擎抽象了共同点使得工作变得简单。

1666264799148.jpg

支持的认证协议有:


OAuth (Facebook, Twitter, Google…) - SAML - CAS - OpenID Connect - HTTP - Google App Engine

LDAP - SQL - JWT - MongoDB - CouchDB - IP address - Kerberos (SPNEGO) - REST API


支持的授权类型有:


Roles/permissions - Anonymous/remember-me/(fully) authenticated - CORS - CSRF - HTTP Security headers


三、引擎特征


  1. 简单
  2. 高效
  3. 强壮


四、十大核心组件


序号 组件英文名称 组件中文名称 功能描述
1 client 客户端 代表一个认证流程,执行登录逻辑并返回用户信息;UI认证的客户端称为间接客户端(indirect client),web服务认证的客户端称为直接客户端
2 authenticator 认证器 用于HTTP客户端认证身份, ProfileService的子组件,ProfileService不仅验证用户身份,还进行用户信息的创建、更新和删除
3 authorizer 授权器 基于网页上下文信息和用户信息进行权限验证
4 matcher 匹配器 定义安全性是否必须应用于安全过滤器
5 config 配置器 通过客户端、授权器和匹配器定义安全配置
6 user profile 用户身份 经过身份验证的用户的配置文件,具有标识符、属性、角色、权限、“记住我”性质和链接标识符
7 web context 用户身份 pac4j实现的 HTTP 请求和响应以及关联表示会话的实现SessionStore的抽象
8 security filter 安全过滤器 根据客户端和授权器的配置,通过检查用户是否经过身份验证以及授权是否有效来保护请求访问的 URL,如果用户未通过身份验证,则对直接客户端执行身份验证或为间接客户端启动登录过程
9 callback endpoint 回调点 表示间接客户端登录流程的结束
10 logout endpoint 登出点 处理应用或者身份服务器的登出


五、项目移植


笔者需要被集成的Web系统是基于Guns后台开发,版本是beetle版本,项目集成CAS基于spring-shiro-cas移植。


5.1 导包


<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-core</artifactId>
   <version>1.4.0</version>
   <exclusions>
       <exclusion>
           <artifactId>slf4j-api</artifactId>
           <groupId>org.slf4j</groupId>
       </exclusion>
   </exclusions>
</dependency>
<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-spring</artifactId>
   <version>1.4.0</version>
</dependency>
<dependency>
    <groupId>io.buji</groupId>
    <artifactId>buji-pac4j</artifactId>
    <version>4.0.0</version>
</dependency>
<dependency>
    <groupId>org.pac4j</groupId>
    <artifactId>pac4j-cas</artifactId>
    <version>3.3.0</version>
</dependency>

5.2 配置

cas:
  client-name: app
  server:
   url: http://127.0.0.1:8080/cas
  project:
   url: http://127.0.0.1:8082/iotProject


5.3 重写认证和授权函数


/**
 * 认证
 *
 * @param authenticationToken
 * @return
 * @throws AuthenticationException
 */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)throws AuthenticationException {
    final Pac4jToken pac4jToken = (Pac4jToken) authenticationToken;
    final List<CommonProfile> commonProfileList = pac4jToken.getProfiles();
    final CommonProfile commonProfile = commonProfileList.get(0);
    logger.info("单点登录返回的信息" + commonProfile.toString());
//        final Pac4jPrincipal principal = new Pac4jPrincipal(commonProfileList,getPrincipalNameAttribute());
    UserAuthService shiroFactory = UserAuthServiceServiceImpl.me();
    User user = shiroFactory.user(commonProfile.getId());
    ShiroUser shiroUser = shiroFactory.shiroUser(user);
    final PrincipalCollection principalCollection = new SimplePrincipalCollection(shiroUser, getName());
    return new SimpleAuthenticationInfo(principalCollection,commonProfileList.hashCode());
}
/**
 * 授权/验权(todo 后续有权限在此增加)
 *
 * @param principals
 * @return
 */
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    UserAuthService shiroFactory = UserAuthServiceServiceImpl.me();
    ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
    List<Long> roleList = shiroUser.getRoleList();
    Set<String> permissionSet = new HashSet<>();
    Set<String> roleNameSet = new HashSet<>();
    for (Long roleId : roleList) {
        List<String> permissions = shiroFactory.findPermissionsByRoleId(roleId);
        if (permissions != null) {
            for (String permission : permissions) {
                if (ToolUtil.isNotEmpty(permission)) {
                    permissionSet.add(permission);
                }
            }
        }
        String roleName = shiroFactory.findRoleNameByRoleId(roleId);
        roleNameSet.add(roleName);
    }
    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    info.addStringPermissions(permissionSet);
    info.addRoles(roleNameSet);
    return info;
}

5.4 调试


5.4.1 CAS验证原理


该图出自CAS官网,传送门

1666265069449.jpg


5.4.2 单点登录流程分析


1.在浏览器中输入项目地址,servlet开始处理HTTP请求


2.过滤器链中的过滤器执行动作逻辑,在ShiroFilterFactoryBean工厂类中定义一个包含4个过滤器的过滤器Map表,分别是3个自定义和一个默认的过滤器UserFilter:


filterChainDefinitionMap.put("/", "securityFilter");
filterChainDefinitionMap.put("/callback", "callbackFilter");
filterChainDefinitionMap.put("/logout", "logoutFilter");
filterChainDefinitionMap.put("/**","user");

3.在securityFilter中,此时还没有任何用户的信息,仅仅是将访问的服务网站重定向到CAS服务器登陆地址,http://127.0.0.1:8080/cas/login?service=http%3A%2F%2F127.0.0.1%3A8082%2FiotProject%2Fcallback%3Fclient_name%3Dapp


4.在登陆网页上填写用户名和密码信息后,继续执行过滤器callbackFilter,该过滤器的功能是利用CasAuthenticator验证ticket获取到中央认证服务器上用户的身份信息,接着BaseClient创建用户信息UserProfile,并将用户信息保存到Session中完成信息的共享,在保存的函数中完成用户主体身份login的流程,完成后重定向到受保护的网站即我们的服务网站


5.请求再次进到过滤器链中,因为服务地址对应的后台访问接口为“/”,对应着主页,先来看一下该函数:


/**
 * 跳转到主页
 */
@RequestMapping(value = "/", method = RequestMethod.GET)
public String index(Model model, HttpServletRequest request, HttpServletResponse response) {
    //获取当前用户角色列表
    ShiroUser user = ShiroKit.getUserNotNull();
    List<Long> roleList = user.getRoleList();
    if (roleList == null || roleList.size() == 0) {
        ShiroKit.getSubject().logout();
        model.addAttribute("tips", "该用户没有角色,无法登陆");
        return "/login.html";
    }
    List<MenuNode> menus = userService.getUserMenuNodes(roleList);
    model.addAttribute("menus", menus);
    return "/index.html";
}

因此又会进入到securityFilter过滤器中,此时用户已经完成认证,认证成功后直接放行进到后台拦截器中即对应的接口函数中,后续需要用到权限的请求doGetAuthorizationInfo()函数即可,至此完成单点登录功能。


5.5 完成


相关文章
|
1天前
|
开发者 UED
Axure“Web高端交互元件库”:产品与设计的得力助手
这套“Web高端交互元件库”精心构建了四大板块内容,分别是登陆首页集合、Web框架集合、表单元件集合以及主流后台组件。每一板块都包含了大量实用且美观的交互元件,设计师与开发者可以根据具体项目需求,快速找到并应用这些元件,从而大大提升工作效率。
|
6天前
|
安全 前端开发 Java
Web端系统开发解决跨域问题——以Java SpringBoot框架配置Cors为例
在Web安全上下文中,源(Origin)是指一个URL的协议、域名和端口号的组合。这三个部分共同定义了资源的来源,浏览器会根据这些信息来判断两个资源是否属于同一源。例如,https://www.example.com:443和http://www.example.com虽然域名相同,但由于协议和端口号不同,它们被视为不同的源。同源(Same-Origin)是指两个URL的协议、域名和端口号完全相同。只有当这些条件都满足时,浏览器才认为这两个资源来自同一源,从而允许它们之间的交互操作。
Web端系统开发解决跨域问题——以Java SpringBoot框架配置Cors为例
|
11天前
|
jenkins 持续交付 开发工具
"引爆效率革命!Docker+Jenkins+GIT+Tomcat:解锁持续集成魔法,一键部署Java Web应用的梦幻之旅!"
【8月更文挑战第9天】随着软件开发复杂度的增加,自动化变得至关重要。本文通过实例展示如何结合Docker、Jenkins、Git与Tomcat建立高效的持续集成(CI)流程。Docker确保应用环境一致性;Jenkins自动化处理构建、测试和部署;Git管理源代码版本;Tomcat部署Web应用。在Jenkins中配置Git插件并设置项目,集成Docker构建Tomcat应用镜像并运行容器。此外,通过自动化测试、代码质量检查、环境隔离和日志监控确保CI流程顺畅,从而显著提高开发效率和软件质量。
34 3
|
17天前
|
NoSQL Java Redis
Spring Boot集成Redis全攻略:高效数据存取,打造性能飞跃的Java微服务应用!
【8月更文挑战第3天】Spring Boot是备受欢迎的微服务框架,以其快速开发与轻量特性著称。结合高性能键值数据库Redis,可显著增强应用性能。集成步骤包括:添加`spring-boot-starter-data-redis`依赖,配置Redis服务器参数,注入`RedisTemplate`或`StringRedisTemplate`进行数据操作。这种集成方案适用于缓存、高并发等场景,有效提升数据处理效率。
71 2
|
4天前
|
数据可视化 数据挖掘 持续交付
Axure Web端元件库:从Quick UI到500+组件的飞跃
在快速变化的数字世界中,产品设计不仅仅是功能的堆砌,更是用户体验的精心雕琢。原型设计作为产品开发过程中的关键环节,其重要性不言而喻。Axure,作为业界领先的原型设计工具,凭借其强大的交互设计和丰富的功能,赢得了全球设计师和开发者的信赖。而Axure Web端元件库,则是这一平台上的一颗璀璨明珠,它以超过500个精心设计的组件为基础,为设计师们打开了一扇通往高效、高质量原型设计的大门。
17 0
|
1月前
|
机器人 Shell 开发者
`roslibpy`是一个Python库,它允许非ROS(Robot Operating System)环境(如Web浏览器、移动应用等)与ROS环境进行交互。通过使用`roslibpy`,开发者可以编写Python代码来远程控制ROS节点,发布和订阅话题,以及调用服务。
`roslibpy`是一个Python库,它允许非ROS(Robot Operating System)环境(如Web浏览器、移动应用等)与ROS环境进行交互。通过使用`roslibpy`,开发者可以编写Python代码来远程控制ROS节点,发布和订阅话题,以及调用服务。
|
1月前
|
缓存 测试技术 API
告别加班!Django/Flask高级技巧,让你的Web开发效率翻倍再翻倍!
【7月更文挑战第15天】探索Django与Flask高效秘籍:**利用模板继承减少重复代码,自动化测试确保质量,缓存提升性能。通过模板继承实现DRY原则,自动化测试框架如Django的`TestCase`和Flask的`pytest`加快调试,缓存机制(Django的低级别缓存API或Flask-Caching)优化页面加载。掌握这些技巧,告别加班,提升开发体验!
152 3
|
1月前
|
安全 开发者 Python
告别迷茫,Django/Flask深入应用指南,让你的Web梦想照进现实!
【7月更文挑战第13天】在Python Web开发中,Django和Flask框架各具特色。Django适合快速构建企业级应用,提供ORM、模板引擎等全面功能;而Flask轻量灵活,适用于小项目和原型开发。通过实例,了解如何启动Django和Flask的基本应用,从创建项目到运行服务器。选择框架应考虑项目需求和个人偏好,不断学习与实践将助你实现Web梦想。
28 1
|
18天前
|
NoSQL Java 关系型数据库
MongoDB保姆级指南(下):无缝集成SpringData框架,一篇最全面的Java接入指南!
前面的两篇文章已经将MongoDB大多数知识进行了阐述,不过其中的所有内容,都基于原生的MongoDB语法在操作。可是,在实际的日常开发过程中,我们并不会直接去接触MongoDB,毕竟MongoDB只能算作是系统内的一个组件,无法仅依靠它来搭建出一整套系统。
|
21天前
|
Java UED
Java Web 中forward 和 redirect 的区别
在Java Web开发中,页面跳转是构建用户界面和实现业务逻辑的重要组成部分。Forward(转发)和Redirect(重定向)是两种常见的跳转方式,它们分别具有不同的特点和适用场景。正确地选择和使用这两种跳转方式,有助于提高Web应用的性能、用户体验和代码可维护性。
32 0

热门文章

最新文章