使用shiro保护你的springboot应用_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 使用shiro保护你的springboot应用

使用shiro保护你的springboot应用

 2018/1/8 6:17:05  wj596  程序员俱乐部  我要评论(0)
  • 摘要:springboot中使用shiro大都是通过shiro-spring.jar进行的整合的,虽然不是太复杂,但是也无法做到spring-boot-starter风格的开箱即用。项目中经常用到的功能比如:验证码、密码错误次数限制、账号唯一用户登陆、动态URL过滤规则、无状态鉴权等等,shiro还没有直接提供支持。jsets-shiro-spring-boot-starter对这些常用的功能进行了封装和自动导入,少量的配置就可以应用在项目中。已实现的功能1、spring-boot
  • 标签:使用 Spring 应用

springboot中使用shiro大都是通过shiro-spring.jar进行的整合的,虽然不是太复杂,但是也无法做到spring-boot-starter风格的开箱即用。项目中经常用到的功能比如:验证码、密码错误次数限制、账号唯一用户登陆、动态URL过滤规则、无状态鉴权等等,shiro还没有直接提供支持。

jsets-shiro-spring-boot-starter对这些常用的功能进行了封装和自动导入,少量的配置就可以应用在项目中。

已实现的功能

1、spring-boot-starter风格的开箱即用。

2、区分ajax请求和普通请求,普通请求通过跳转来响应未登陆和未授权,AJAX请求通过状态码和消息响应未登陆和未授权。

3、集成jcaptcha验证码。

4、密码输入错误,重试次数限制。

5、账号唯一用户登陆,一个账号只允许一个用户登陆。

6、redis缓存支持,认证\授权数据缓存同步

7、动态URL过滤规则。

8、无状态认证授权支持,共存有状态和无状态两种鉴权方式,无状态鉴权支持JWT(JSON WEB TOKEN)、HMAC(哈希消息认证码)两种协议

9、在线session管理,强制用户下线功能。

计划的功能

1、cas单点登陆集成

2、oauth2.0支持

此文介绍应用jsets-shiro-spring-boot-starter来为一个springboot应用提供鉴权支持,限于篇幅,没有贴出源码只贴出了演示效果,您可以在文末"项目文档、源码"中获取全部源码。

?

?

基本配置

1、在application.properties添加下面配置:

class="hljs bash">#是否启用验证码验证,不配置默认不启用
jsets.shiro.jcaptcha-enable=true
#是否启用账号唯一用户登陆(一个账号只允许一个用户登陆,后面登陆的用户踢出前面登陆的用户),不配置默认不启用
jsets.shiro.keep-one-enabled=true
#是否启用强制用户下线(系统管理员通过session操作迫使指定用户下线),不配置默认不启用
jsets.shiro.force-logout-enable=true
#登陆页面
jsets.shiro.login-url=/login
#登陆成功页面
jsets.shiro.login-success-url=/index
#无权限调转页面
jsets.shiro.unauthorized-url=/unauthorized
#用户被踢出后跳转的页面,keep-one-enabled=true时此项有用,不配置默认login-url
jsets.shiro.kickout-url=/kickout
#用户被强制下线后跳转的页面,force-logout-enable=true时此项有用,不配置默认login-url
jsets.shiro.force-logout-url=/force_logout
#密码错误最大次数,不配置默认无限次
jsets.shiro.passwd-max-retries=5
#基本静态过滤规则
jsets.shiro.filte-rules[0]=/assets/**-->anon
jsets.shiro.filte-rules[1]=/login/**-->authc
jsets.shiro.filte-rules[2]=/logout/**-->logout
jsets.shiro.filte-rules[3]=/**-->user,keepOne,forceLogout

2、实现Controller类IndexAction,主要用来做各种跳转。
3、实现登陆界面login.html
4、实现主页index.html

如果此时启动springboot应用,会打印出组件预置的体验账号和密码:


? ?

使用这个账号和密码就可以登陆系统了。

验证码为空的情况 ?
账号或密码错误的情况 ? 登陆成功情况 ?

如果您使用其他浏览器或者使用其他的电脑用这个账号登陆,当前登陆的用户会被后来登陆的用户踢出。

当前用户被踢出 ? ?

接入用数据、密码输入错误超限处理

上面跑起来的应用,使用的是组件中提供的体验账号和密码,实际项目中肯定要接入自己的用户数据,角色数据、权限数据。
1、实现ShiroAccountProvider接口ShiroAccountProviderImpl,作用是为组件提供鉴权数据。
2、实现PasswdRetryLimitHandler接口ShiroFilteRulesProviderImpl,作用是响应密码输入错误次数超限时的回调。
3、实现DemoJsetsShiroConfiguration继承自JsetsShiroConfigurationAdapter,用来设置ShiroAccountProviderImpl实现和ShiroFilteRulesProviderImpl。

如果此时重启系统,将不再使用体验账号,而是使用您自己的账号数据进行鉴权。
当用户密码输入错误到达限制次数后将会锁定用户。


重试错误提示 ? 错误次数超限锁定 ? ?

动态URL过滤规则

大部分系统的安全模型都是RBAC(Role-Based Access Control 基于角色的权限访问控制),使用用户--角色--资源(URL)的对应关系来表示并存储。

能够访问某个资源可以看成是一种权限,资源(URL)就是这个权限的表示,角色就是权限的集合。访问一个资源(URL)时候都会检查当前用户是否拥有对应的角色。

假如有资源,文章删除/article/delete、文章编辑/article/update、文章发布/article/publish。编辑角色(role_editor)拥有编辑的权限,主编角色(role_chief)拥有删除和发布的权限,这样的URL过滤规则在shiro中表示为:

article/update=roles[role_editor]
article/delete=roles[role_chief]
article/publish=roles[role_chief]

如果系统中如果有几十个上百个资源(URL),需要这样细粒度的权限控制,静态配置显然是困难的。好在shiro中提供了基于AOP的方式可以进行这样的分散控制,类似于这样:

@RequiresRoles("role_editor")
function">public void update(Article article){
}

但是如果角色-资源的对应关系发生变更,或者添加了角色,那就只能修改配置或者代码了,还得要重新启动系统才能使得这些变更生效。

实际开发中则更希望通过URL进行集中的权限控制,能够从数据库中查询出角色-资源的对应数据,生成URL过滤规则,当角色-资源的对应关系发生变更时能够刷新这些URL过滤规则。

在jsets-shiro-spring-boot-starter中通过ShiroFilteRulesProvider为组件提供动态过滤规则。
1、实现ShiroFilteRulesProvider接口ShiroFilteRulesProviderImpl
2、在DemoJsetsShiroConfiguration的中设置ShiroFilteRulesProviderImpl。

从角色列表中能看到角色"role_admin"没有文章编辑的权限。

角色列表 ?

进入"文章管理"界面,点击"编辑"按钮,会发现因权限不足不能操作。

权限不足 ?

重新为角色"role_admin"分配资源,添加"修改文章"。

资源分配 ?

再次点击"编辑"文章就可以操作了。


角色验证成功 ?

当然,实际项目中是不会让用户看到不具的菜单或按钮的。

?


无状态鉴权

无状态(Stateless)鉴权通常应用在微服务(REST API)架构中,使用数字摘要(签名)技术生成一个token作为认证和授权的凭证,整个认证和授权过程不依赖于cookie或session,服务端不保留客户端状态因此每次请求都要携带这个token。
jsets-shiro-spring-boot-starter提供两种无状态鉴权方式,分别是散列消息认证码(HMAC)、JSON WEB TOKEN(JWT)。
HMAC适合端到端的鉴权,即客户端拿着签名让服务端进行验签。
JWT适合客户端询问系统B是否有权访问系统C和系统N如果有请开份凭证,然后拿着凭证让系统C和系统N进行验签。

1、在application.properties添加HMAC或者JWT的相关配置

#是否启用HMAC,不配置默认不启用
jsets.shiro.hmac-enabled=true
#HMAC签名算法,不配置默认HmacMD5,hmac-enabled=true时此项有用
#jsets.shiro.hmac-alg=HmacMD5
#HMAC签名秘钥,hmac-enabled=true时此项有用
jsets.shiro.hmac-secret-key=123456789.abcdefg.
#HMAC签名有效期,不配置默认1分钟,hmac-enabled=true时此项有用
#jsets.shiro.hmac-period=60000
#是否启用JWT鉴权,不配置默认不启用
jsets.shiro.jwt-enabled=true
#JWT签名全局秘钥,jwt-enabled=true时此项有用
jsets.shiro.jwt-secret-key=123456789.abcdefg.

2、配置URL拦截规则,示例项目中使用的是动态配置。

#匹配此路径的URL,需要通过hmac认证并具有role_admin角色
jsets.shiro.filte-rules[3]=/restApi/delete*-->hmacRoles[role_admin]
#匹配此路径的URL,需要通过hmac认证
jsets.shiro.filte-rules[4]=/restApi/**-->hmac
#匹配此路径的URL,需要通过jwt认证并具有role_admin角色
jsets.shiro.filte-rules[5]=/restApi2/delete*-->jwtRoles[role_admin]
#匹配此路径的URL,需要通过jwt认证
jsets.shiro.filte-rules[6]=/restApi2/**-->jwt

?

访问这些api会使用HMAC或者JWT进行鉴权。


hmac验签成功 ?

当超过签名的有效期后,再次用这个签名进行鉴权,签名将过期失效。


签名过期 ?

生成签名之后,手动在签名后面加了一个字符"3",说明请求内容和签名不符,即请求发生了篡改,签名无效。


签名无效 ?

HMAC和JWT也具有权限验证的能力,我们用guest账号登陆,点击“请求delete”。


权限不足 ?

不生成令牌直接点击请求,因为没有令牌会要求进行身份认证。


未进行身份认证 ? ?

在线用户、强制下线

展示所有活跃的用户(session),系统管理员可以强制这些用户下线。

当前在线用户 当前用户被管理员强制下线 ?

项目文档、源码

1、jsets-shiro-spring-boot-starter项目详情请参见:jsets-shiro-spring-boot-starter
2、应用示例源码请参见:jsets-shiro-demo
3、jsets-shiro-spring-boot-starter使用说明请参见:使用说明

如果您对这个组件感兴趣请star收藏,在使用这个组件中有任何问题或意见都可以在这里交流,欢迎提交代码。

发表评论
用户名: 匿名