前言java
此框架由小菜独立开发,而且已经在生产环境中运行大约一年时间。git
也就是说,Security 框架写出来有一段时间了,可是一直没有公布、开源,通过不断迭代完善,终于算是拿得出手啦~github
Security 框架存在的意义并非为了替代 Shiro 或 Spring Security ,并且提供另外一种选择。web
当读者由于现有安全框架的复杂繁琐而苦恼时,为何不尝试一下 Security 呢?
redis
请原谅小菜在本文直接照搬 GitHub 的 README,之后小菜会陆续完善使用教程和相关 Demo ,敬请关注~spring
最后但愿读者能给出宝贵意见、及时反馈问题,来帮助小菜继续完善框架。数据库
README后端
本框架基于Spring MVC
开发,是一款轻量级的安全认证框架。缓存
抛弃Shiro
、Spring Security
等安全框架繁琐的配置,改成注解实现权限管理,配合Spring MVC
的RequestMapping
注解,完美实现细粒度的权限控制。安全
本框架以Redis
做为持久化数据库,Ehcache
做为内存级缓存,知足高性能需求。
本框架删繁就简,以角色做为权限认证的惟一标准,并不是传统的RBAC
权限模型,在这里没有权限的概念,只有角色,角色就是权限,权限就是角色,所以本框架适合应用于互联网项目,尤为适合先后端分离模式下的后端接口。
添加Maven项目依赖
<!-- security frame work --> <dependency> <groupId>org.yangyuan</groupId> <artifactId>security</artifactId> <version>0.0.1</version> </dependency>
与Spring MVC集成
<!-- 扫描spring注解 --> <context:component-scan base-package="com.yourself, org.yangyuan.security" /> <!-- 身份认证拦截器 --> <mvc:interceptors> <bean class="org.yangyuan.security.servlet.SecurityInterceptor"></bean> </mvc:interceptors>
添加配置文件
将本项目中的security.properties
文件拷贝到真实项目resources
根目录下,与log4j.properties
位置相同,即保证编译后这个文件在classes
目录下。
security.properties说明
#Session有效期 #这是一个相对值,相对于用户最后一次访问的时间 #也就是说,只有当用户超过此时间不活跃,Session才会失效 #单位秒(s) session.expiresMilliseconds=2592000000 #是否启用Session垃圾回收器 session.gc.open=true #Session垃圾回收器Lua脚本 session.gc.script=for i=48,83,1 do local partition if(i > 57) then partition = string.char(i + 39) else partition = string.char(i) end local setkey = 'security:session:set:'..partition local principals = redis.call('ZRANGEBYSCORE', setkey, '-inf', ARGV[1]) redis.call('ZREMRANGEBYSCORE', setkey, '-inf', ARGV[1]) if(principals and (table.maxn(principals) > 0)) then for ii,vv in ipairs(principals) do local hashkey = 'security:session:hash:'..partition redis.call('HDEL', hashkey, vv) end end end #Session垃圾回收器执行时间间隔 #单位秒(s) session.gc.gcDelaySecond=86400 #cookie名称 cookie.name=sid #cookie域名 cookie.domain=.cospace.xyz #cookie路径 cookie.path=/ #此配置为true时,cookie没法经过js脚本操做 cookie.http_only=true #是否启用HTTPS cookie.secure=true #cookie有效期,通常不须要改动,目前设置的是最大值,至关于永不过时 #由于cookie的生命周期由服务器端维护,因此客户端不须要关心过时时间 cookie.max_age=315360000 #Redis客户端链接工厂 #负责提供Redis客户端链接 common.redisResourceFactory=cc.cospace.web.security.dao.DefaultRedisResourceFactory #安全管理器实现 core.securityManager=org.yangyuan.security.core.DefaultSecurityManager #安全惟一标识生成器实现 core.principalFactory=org.yangyuan.security.core.DefaultPrincipalFactory #缓存管理器实现 core.cacheManager=org.yangyuan.security.core.DefaultCacheManager #是否复用客户端subject #若是设为true,客户端登录时若是携带有subject信息,那么复用此subject,再也不建立新的subject #若是设为false,则登陆时忽略客户端携带的subject信息,老是建立新的subject core.useClientSubjectLogin=false #并发主题控制器 #[org.yangyuan.security.core.MultiportConcurrentSubjectControl]容许同一个帐号同时在不一样客户端登录 #[org.yangyuan.security.core.SingleConcurrentSubjectControl]同一个帐号同一时刻只能在一个客户端登录,若是以前在其余客户端登录过,那么以前的登录将失效 #[org.yangyuan.security.core.RefuseConcurrentSubjectControl]同一个帐号同一时刻只能在一个客户端登录,若是以前在其余客户端登录过,那么本次登录将会失败,除非其余客户端主动退出登录 core.concurrentSubjectControl=org.yangyuan.security.core.MultiportConcurrentSubjectControl #认证回调 #此处理器用来响应认证结果(成功、失败、拒绝访问) #具体的响应依赖于具体的业务,框架只负责通知认证结果 core.securityAuthHandler=cc.cospace.web.security.core.DefaultSecurityAuthHandler #ehcache缓存数据访问层(缓存层) dao.ehcacheSessionDao=org.yangyuan.security.dao.EhcacheSessionDao #redis数据访问层(持久化层) dao.redisSessionDao=org.yangyuan.security.dao.RedisSessionDao #持久化数据源(用户名密码模式) dao.jdbcRealm=org.yangyuan.security.realm.jdbc.JdbcRealm #第三方数据源 dao.remoteRealm=org.yangyuan.security.realm.remote.RemoteRealm #本地认证数据访问层(用户名密码模式) dao.jdbcSessionDao=org.yangyuan.security.dao.JdbcSessionDao #第三方登陆认证数据访问层 dao.remoteSessionDao=org.yangyuan.security.dao.RemoteSessionDao #用户名密码模式登陆适配器 #此适配器实现安全认证与具体项目用户数据存储之间的解耦 dao.jdbcRealmAdaptor=userService #第三方登陆适配器 #此适配器实现安全认证与具体项目用户数据存储之间的解耦 dao.remoteRealmAdaptor=userService #cache在内存中最多能够存放的元素的数量。 #0表示没有限制。 #若是放入cache中的元素超过这个数值,有两种可能: #一、若overflowToDisk的属性值为true,会将cache中多出的元素放入磁盘文件中。 #二、若overflowToDisk的属性值为false,会根据memoryStoreEvictionPolicy的策略替换cache中原有的元素。 cache.maxElementsInMemory=10000 #缓存是否永驻内存。 #若是值是true,cache中的元素将一直保存在内存中,不会由于时间超时而丢失。 #所以在这个值为true的时候,timeToIdleSeconds和timeToLiveSeconds两个属性的值就不起做用了。 cache.eternal=false #内存中的元素数量溢出是否写入磁盘。 #系统会根据标签<diskStore path="java.io.tmpdir"/>中path的值查找对应的属性值。 #若是系统的java.io.tmpdir的值是/temp,写入磁盘的文件就会放在这个文件夹下,文件的名称是cache的名称,后缀名为data。 cache.overflowToDisk=false #是否持久化内存中的缓存到磁盘。 #当这个属性的值为true时,系统在初始化的时候会在磁盘中查找文件名为cache名称,后缀名为index的的文件,如CACHE_FUNC.index。 #这个文件中存放了已经持久化在磁盘中的cache的index,找到后把cache加载到内存。 cache.diskPersistent=false #访问cache中元素的最大间隔时间。 #若是超过此时间cache中的某个元素没有任何访问,那么这个元素将被从cache中清除。 cache.timeToIdleSeconds=900 #cache中元素的总生存时间,cache中的某个元素从建立到消亡的时间。 #从建立开始计时,当超过这个时间,这个元素将被从cache中清除,即使是这个元素被频繁访问。 cache.timeToLiveSeconds=7200 #内存存储与释放清理策略 #LRU最近最少使用 #LFU历史访问频率最低 #FIFO先进先出 cache.memoryStoreEvictionPolicy=LRU #普通验证码有效期 #单位s captcha.normal.expireSecond=900 #普通验证码屡次发送最短期间隔 #单位s captcha.normal.minIntervalSecond=50 #图形验证码有效期 #单位s captcha.image.expireSecond=600 #图形验证码错误统计周期 #单位s captcha.image.wrongPeriodSecond=60 #图形验证码统计周期内容许最大错误次数 captcha.image.periodMaxWrongCount=3
具体业务类实现
RedisResourceFactory
接口。SecurityAuthHandler
接口。JdbcRealmAdaptor
接口。RemoteRealmAdaptor
接口。 security.properties
文件中配置的全部类型,能够配置成完整类名(包名+类名),也能够配置成spring IOC
中的Bean
名称,根据业务状况自由选择。
通常来说,除非须要本身扩展框架,不然只须要实现具体业务类,而后修改一下cookie相关配置便可,其余配置项都可使用默认配置。
验证码模块使用介绍
验证码模块只实现了公共逻辑,并无实现具体的发送逻辑,目的是留给使用者更多的操做空间,使得框架具备更强的适应性。
若是须要使用验证码模块,最佳实践以下:
AbstractPhoneEmailSecurityCaptchaService
,继承模块中的AbstractPhoneEmailSecurityCaptcha
,实现newCode
、sendToPhone
、sendToEmail
方法,这三个方法是公共方法,但必须交给使用者实现,由于不一样的项目发送短信、邮件的方式不尽相同,生成验证码的规则也不尽相同。而后在项目中以AbstractPhoneEmailSecurityCaptchaService
为基础,派生出具体的业务类,好比发送注册验证码的业务类RegisterCaptchaService
,继承AbstractPhoneEmailSecurityCaptchaService
,而后实现name
、title
、content
方法便可。AbstractSecurityImageCaptchaService
,继承模块中的AbstractSecurityImageCaptcha
,实现newCode
方法,生成的验证码取决于实际项目中图形生成器的能力,避免生成没法被图形生成器识别的字符,固然,图形生成器您本身实现,看着办。而后在项目中以AbstractSecurityImageCaptchaService
为基础,派生出具体的业务类,好比登录图形验证码的业务类LoginImageCaptchaService
,继承AbstractSecurityImageCaptchaService
,而后实现name
方法便可。经过以上描述能够看出,验证码模块只是封装了繁琐的验证码发送标记、验证等操做,并不干预具体的发送实现。
使用者封装好适合本身的抽象基类后,不论任何业务,只须要继承抽象基类便可轻松实现,并自然实现业务之间的隔离。
总结一下,使用者只须要关注发送手机短信、发送邮件、生成验证码文本、生成验证码图片具体实现,而后根据具体业务设定好验证码标题、验证码内容、业务名称(用来隔离业务)便可。
通过前期配置以后,使用就很是简单了!
只须要在Controller
层使用Security
注解便可,Security
注解具体使用方法请参考源码注释。
本框架只关注角色认证,而不关注角色的存储、定义,完全实现安全认证框架与实际项目之间的解耦。
在定义角色名称时,不该该出现框架已经占用的关键字,包括:[
、]
、{
、}
、>
、<
、,
、:
,不然会引发冲突。
GitHub 项目地址