最近有个小项目,采用公司内部的安全认证架构的话太重,就采用shiro来集成了。
各种配置也是网上一顿摘抄,根据自身情况进行的修改
一、项目的认证需求:
1、登录/登出
2、用户/岗位/资源 权限配置
二、数据库表结构
shiro只负责认证等逻辑,权限相关的表还是需要自己设计
这里就复用我们以前项目的表结构,其他大部分字段都没有用
一共有5张表:(附件createTable.sql是几张表的建表及数据:mysql)
1、t_common_grade 岗位表
2、t_common_gradetask 岗位资源表
3、t_common_task 资源表
4、t_common_user 用户表
5、t_common_usergrade 用户岗位表
三、集成web项目(SSH)
1、引入jar:shiro-all-1.2.4.jar及其相关依赖
2、web.xml配置
在web.xml中增加拦截器:
<!-- shiro权限配置 开始 --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- shiro权限配置 结束 -->
注意,如果项目没有什么特殊需求的话,该拦截器最好放在第一个位置
3、与spring集成的配置文件:applicationContext-shiro.xml 添加到spring总配置中
a:这个项目采用 shiro JdbcRealm配置方式
b:第28 - 33行是和数据库表相关的配置,主要就是获取用户、获取用户角色(岗位)、获取岗位权限(资源)
c:需要注意的是,如果数据库中用户的密码采用MD5加密的话,需要增加特殊配置,见下面的注释
MD5加密可以采用shiro带的工具类Md5Hash:String passwd = new Md5Hash("yourPwd").toString();
d:第51 - 54行是具体的拦截策略 根据自己项目的实际情况进行配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd" default-autowire="byName" default-lazy-init="true"> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"></bean> <!-- 如果数据库密码是MD5存储的 那么下面的配置是必须的 --> <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.Md5CredentialsMatcher"></bean> <!-- 缓存管理 --> <bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager"></bean> <!-- 使用Shiro自带的JdbcRealm类 指定密码匹配所需要用到的加密对象 指定存储用户、角色、权限许可的数据源及相关查询语句 --> <bean id="jdbcRealm" class="org.apache.shiro.realm.jdbc.JdbcRealm"> <property name="credentialsMatcher" ref="credentialsMatcher"></property> <property name="permissionsLookupEnabled" value="true"></property> <property name="dataSource" ref="dataSource"></property> <property name="authenticationQuery" value="SELECT userpwd FROM T_COMMON_USER WHERE usercode = ?"></property> <property name="userRolesQuery" value="SELECT ug.gradeid from t_common_user u,t_common_usergrade ug where u.u_id=ug.u_id and u.usercode=?"></property> <property name="permissionsQuery" value="select distinct t.taskcode from t_common_task t,t_common_gradetask gt where t.task_id = gt.taskid and gt.gradeid=?"></property> </bean> <!-- Shiro安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="jdbcRealm"></property> <property name="cacheManager" ref="cacheManager"></property> </bean> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- Shiro的核心安全接口,这个属性是必须的 --> <property name="securityManager" ref="securityManager"></property> <!-- 要求登录时的链接(登录页面地址),非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 --> <!-- <property name="loginUrl" value="/security/login"></property> --> <!-- 登录成功后要跳转的连接(本例中此属性用不到,因为登录成功后的处理逻辑在LoginController里硬编码) --> <!-- <property name="successUrl" value="/" ></property> --> <!-- 用户访问未对其授权的资源时,所显示的连接 --> <property name="unauthorizedUrl" value="/"></property> <property name="filterChainDefinitions"> <value> /login/*=anon <!-- 不拦截登录/登出界面的请求 --> /bs/**=anon <!-- 不拦截登录界面等使用的JS CSS文件 --> /layout/**=anon <!-- 不拦截SiteMesh3使用的JS CSS文件 --> /**=authc <!-- 拦截除上面之外的所有请求 --> </value> </property> </bean> </beans>
4、登录Action
a:登录认证
UsernamePasswordToken token = new UsernamePasswordToken("yourUserName",yourPassWord); token.setRememberMe(true); Subject subject = SecurityUtils.getSubject(); if (subject.isAuthenticated()) { //如果认证成功 ..... }else{ //如果认证失败 }
b:登出
Subject subject = SecurityUtils.getSubject(); subject.logout();
5、前台界面权限配置
可以通过<shiro:hasPermission>等一堆标签达到粗颗粒或者精准的控制
<div class="box-footer"> <div class="row"> <div class="col-xs-6"></div> <div class="col-xs-2"> <shiro:hasPermission name="gqis_config_menu_add"> <button type="button" class="btn btn-block btn-info" id="menuAdd">增加</button> </shiro:hasPermission> </div> <div class="col-xs-2"> <shiro:hasPermission name="gqis_config_menu_update"> <button type="button" class="btn btn-block btn-info" id="menuUpdate">修改</button> </shiro:hasPermission> </div> <div class="col-xs-2"> <button type="button" class="btn btn-block btn-info" id="menuDelete">删除</button> </div> </div>
四、总结
这里的配置只是shiro功能的一角,但是对于一个小项目来讲,够用了:不要为了技术而技术,需求应用才是最大的推动力