切换原因
在shiro-1.3.x
以后的版本中,shiro-cas
包里面的所有类都被标识为deprecated
,详细:https://github.com/apache/shiro/pull/33。
个人认为不继续维护shiro-cas
而切换到pac4j
主要有以下几点原因:
shiro-cas
非常的不灵活,比如在CasFilter
里onLoginSuccess(..)
登录成功事件,就只考虑到了通过cas跳转过来的情况,直接就执行了issueSuccessRedirect(..)
跳转到保存的请求地址,并没有考虑到如果是ajax请求该如何处理。- 认证协议太多,如果需要扩展一个微博登录(oauth2)那么还得加一个
shiro-oauth
?pac4j原生就支持很多的认证协议 OAuth (Facebook, Twitter, Google…) - SAML - CAS - OpenID Connect - HTTP - OpenID - Google App Engine LDAP - SQL - JWT - MongoDB - Stormpath - IP address
pac4j介绍
pac4j定位是一个java安全引擎(Java security engine),所以不止包含支持各种认证协议进行登录,同时也支持 角色权限的管理、记住登录、CORS、CSRF、输出Http安全头 等功能,并且可以和很多著名的框架结合,比如官方列举的 J2E、Spring Web MVC (Spring Boot)、Spring Security (Spring Boot)、Shiro、Play 2.x、Vertx、Spark Java、Ratpack、Undertow、CAS server、Dropwizard、Knox、Jooby 。
由于我们的项目使用的Apache shiro
,并且也经过了很长时间的开发和对shiro的扩展,所以如果没有特别大的需求,不会去替换掉shiro
框架,所以采用了buji-cas4j来提供shiro和pac4j的结合。
pac4j大量用到了java8的特性编写,所以最低配置要求java8
以及shiro 1.3.x
+。
替换shiro-cas
引入依赖
去掉shiro-cas相关bean
各自对shiro-cas扩展程度不同,基本上去掉依赖以后所有ide报错的地方都需要改,这里就记录一下我们项目中修改的东西:
- 自定义的Realm不再继承自CasRealm,修改为
Pac4jRealm
- 去掉CasFilter过滤器,改用buji-pac4j提供的
CallbackFilter
(下面会介绍如果配置这个bean) - 将CasSubjectFactory修改为
Pac4jsubjectFactory
配置pac4j-cas
- 首先定义
CasConfiguration(loginUrl,prefixUrl)
,loginUrl为完整的cas登录地址,比如client项目的https://passport.sqzryang.com/login?service=https://client.sqzryang.com
,prefixUrl则为cas路径前缀,根据cas的版本号拼接请求地址,用于验证sts是否正确并且返回登录成功后的信息。
- 定义
CasClient
,propertyconfiguration(CasConfiguration)
andcallbackUrl(String)
,在pac4j中,每一个client相当于一种认证协议,比如我们需要weibo登录则应该配置一个WeiboClient
,具体回掉的时候应该采用哪个client进行验证授权则需要下面配置的Clients
- 定义
Clients
,在这里面可以定义你所有的Client以及默认的client还有关于如何区分回掉的哪个client应该取某个参数的配置,具体详细看源码 - 定义
Config
,在config里面还有关于权限方面的配置以及session存储的一些配置,由于这部分我交给shiro去管理,所以只传入了clients
即可 - 以上四个都是
pac4j
的配置,接下来配置一个由buji-pac4j
提供用于和shiro结合的filter:CallbackFilter
,直接传入config
即可 - 定义好CallbackFilter以后,在
ShiroFilterFactoryBean
中注册好filters
,并且配置好filterChainDefinitions
具体各个bean的一些基本概念Main concepts and components,一个稍微全面点的配置:
1 | <bean id="casClientConfiguration" class="org.pac4j.cas.config.CasConfiguration"> |
其他修改地方
- 登录后 Principal 为
Pac4jPrincipal
对象,获取cas传递回来的username,通过:String username = pac4jPrincipal.getProfile().getId();
- 如果开启了缓存,应重写权限缓存以及认证缓存的key值,在
AuthorizingRealm
中的getAuthorizationCacheKey
以及getAuthenticationCacheKey
,推荐使用username来作为缓存key
1 |
|
- 通过默认的
CallbackFilter
登录成功以后,会直接redirectToOriginallyRequestedUrl
,但是在pac4j里面没有再去读取被shiro userfilter检测到未登录后存在session中的SavedRequest
,而是读取org.pac4j.core.context.Pac4jConstants#REQUESTED_URL
,因此重写UserFilter中的saveRequest
适配pac4j
1 |
|
最后
以上配置以后基本就能跑起来了,但是还是有很多细节的地方需要去处理,后面会慢慢写出来,比如如何去配置jasig cas
通过ajax来登录,以及相比Spring Security
shiro原生所缺乏的 csrf cors http头部安全 功能通过pac4j都可以去实现…