1.当然是先建表
Create Table CREATE TABLE `role` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `rolecode` varchar(255) DEFAULT NULL COMMENT '角色编码', `rolename` varchar(255) DEFAULT NULL COMMENT '角色名称', `remark` varchar(255) DEFAULT NULL COMMENT '说明信息', `status` int(11) DEFAULT NULL COMMENT '使用状态1在用/0弃用', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色表' Create Table CREATE TABLE `user_role` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `user_id` int(11) DEFAULT NULL COMMENT '用户ID', `role_id` int(11) DEFAULT NULL COMMENT '角色ID', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户角色关系表' Create Table CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `username` varchar(255) DEFAULT NULL COMMENT '用户昵称', `usercode` varchar(255) DEFAULT NULL COMMENT '员工工号', `password` varchar(255) DEFAULT NULL COMMENT '登录密码', `phone` varchar(255) DEFAULT NULL COMMENT '联系电话', `mark` varchar(255) DEFAULT NULL COMMENT '备注', `status` int(11) DEFAULT NULL COMMENT '使用状态1在用/0弃用', `lastlogin` datetime DEFAULT NULL COMMENT '最近一次登录时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表' Create Table CREATE TABLE `resource` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `parentId` int(11) DEFAULT NULL COMMENT '上级资源ID', `resourcename` varchar(255) DEFAULT NULL COMMENT '资源名称', `url` varchar(255) DEFAULT NULL COMMENT '资源访问url', `resourcecode` varchar(255) DEFAULT NULL COMMENT '资源标识', `status` int(11) DEFAULT NULL COMMENT '使用状态1在用/0弃用', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='资源表' Create Table CREATE TABLE `role_resource` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `role_id` int(11) DEFAULT NULL COMMENT '角色ID', `resource_id` int(11) DEFAULT NULL COMMENT '资源ID', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色资源关系表'
这是五张表,因为没有外键关系,所以以后要用sql控制多对多的关系
2.贴一下自定义的拦截器
/** * * JAVA Realm * 内部重写了用户认证与查询授权两个方法 * * @author Administrator * @version 产品版本信息 Dec 1, 2017 姓名(邮箱) 修改信息 */ public class MyRealm extends AuthorizingRealm { @Autowired LoginService loginService; public MyRealm() { } // 授权 后台添加@RequiresPermissions的Controller @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 获取用户名 User user = (User) principals.getPrimaryPrincipal(); String usercode = user.getUsercode(); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); try { // 手工指定 数据源 ,若开启事务控制设置,则需打开此代码 /* DynamicDataSourceHolder.setDataSource("db_local_eventanalysis_test"); */ // 获取角色下的权限,在这里查询出来的权限,与 @RequiresPermissions("resource:query")的resource:query作比较。如果权限集合中有resource:query这个标签就通过,不存在的话就转发到无权页面 authorizationInfo.setStringPermissions(loginService.getPerms(usercode)); System.out.println("usercode:" + usercode + " permission:" + authorizationInfo.getStringPermissions()); } catch (SQLException e) { e.printStackTrace(); } // 设置 return authorizationInfo; } // 用户登录,用户身份认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) { UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token; String usercode = usernamePasswordToken.getUsername(); String password = String.valueOf(usernamePasswordToken.getPassword()); // password = CryptUtil.psdCrypt(password, usercode); User user = null; try { // 手工指定 数据源 若开启事务控制设置,则需打开此代码 /* DynamicDataSourceHolder.setDataSource("db_local_eventanalysis_test"); */ user = loginService.execute(usercode); } catch (SQLException e1) { e1.printStackTrace(); System.out.println(e1); } // 验证员工工号是否存在 if (user != null && password.equals(user.getPassword())) { // 验证密码是否匹配 Calendar calendar = Calendar.getInstance(); String lastlogin = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(calendar.getTime()); user.setLastLogin(lastlogin); try { loginService.setLastLogin(user);// 更新最近一次登陆时间 } catch (SQLException e) { e.printStackTrace(); } // 保存用户信息 return new SimpleAuthenticationInfo(user, user.getPassword(), this.getName()); } else { throw new AuthenticationException(); } } }
3.配置文件
shiro.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd" default-lazy-init="true"> <!-- 配置Realm,自己定义的myRealm,必须继承AuthorizingRealm --> <bean id="myRealm" class="com.travelsky.updateDatabase.shiro.MyRealm"> <property name="cacheManager" ref="cacheManager" /> </bean> <!-- 2. 配置cacheManager(缓存管理) --> <bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager" /> <!-- 1. 配置securityManager,也就是shiro的核心。 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="myRealm" /> <!-- 缓存管理器 --> <property name="cacheManager" ref="cacheManager" /> </bean> <!-- <bean id="logout" class="org.apache.shiro.web.filter.authc.LogoutFilter"> <property name="redirectUrl" value="/login/logout" /> </bean> --> <!-- 配置shiroFilter id必须和web.xml 文件中配置的DelegatingFilterProxy的filter-name一致 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!-- Shiro的核心安全接口,这个属性是必须的 --> <property name="securityManager" ref="securityManager" /> <!-- 要求登录时的链接(可根据项目的URL进行替换),非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 --> <property name="loginUrl" value="/login/execute" /> <!-- 登录成功后要跳转的连接 --> <property name="successUrl" value="/common/main.jsp" /> <!-- 用户访问未对其授权的资源时,所显示的连接 --> <property name="unauthorizedUrl" value="/common/no_authority.jsp" /> <!-- <property name="filters"> <map> <entry key="logout" value-ref="systemLogoutFilter"/> </map> </property> --> <!-- Shiro权限过滤过滤器定义 --> <property name="filterChainDefinitions"> <value> <!-- 配置哪些页面需要受保护 以及访问这些页面需要的权限anon可以被匿名访问,或者说游客可以访问 authc必须认证之后才能访问,即登录后才能访问的页面 --> <!-- /logout=logout --> </value> </property> </bean>
<!-- 保证实现了Shiro内部lifecycle函数的bean执行 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> <!-- AOP式方法级权限检查 --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"> <property name="proxyTargetClass" value="true" /> </bean> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager" /> </bean></beans>
3.首先是添加用户,shiro整合比较难的就是前期框架的搭建,用户要先在存入入数据库才能验证
<select id="findUserList" resultType="User" parameterType="User"> SELECT u.id, u.usercode, u.username, u.phone, u.lastlogin, r.rolename, u.mark FROM user u left join user_role ur on u.id = ur.user_id left join role r on ur.role_id = r.id WHERE 1=1 AND u.status=1 <if test="username != null and username != '' "> AND username=#{username} </if> <if test="usercode !=null and usercode != '' "> AND usercode=#{usercode} </if> ORDER BY id DESC </select>
这个方法调用的是
doGetAuthenticationInfo的方法
在不同的路径下访问也会走这个方法shiro.xml
<!-- 要求登录时的链接(可根据项目的URL进行替换),非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 --> <property name="loginUrl" value="/login/execute" />
4.添加资源
这里要先设置资源父节点
<!-- 添加资源 --> <insert id="addResource" parameterType="resource"> INSERT INTO resource(parentId,resourcename,url,resourcecode,status) VALUES(#{parentId},#{resourcename},#{url},#{resourcecode},1) </insert>
5.添加角色
<!-- 添加角色 --> <insert id="addRole" parameterType="Role"> INSERT INTO role (rolecode,rolename,remark,STATUS) VALUES (#{rolecode},#{rolename},#{remark},1) </insert>
重点:角色与资源关联,联系到role_rosource表
/** * 为角色重新分配拥有的权限资源 */ @Override public boolean updateResourceByRoleid(String roleId, String resourceIds) throws SQLException { RoleResourceRelation relation = new RoleResourceRelation(); relation.setRole_id(Integer.parseInt(roleId)); roleDao.deleteRoleResourceRelationByRoleId(Integer.parseInt(roleId)); String[] split = resourceIds.split(","); for (String str : split) { if (str != null && str != "") { relation.setResource_id(Integer.parseInt(str)); roleDao.insertRoleResourceRelation(relation); } } return true; }
sql
<insert id="insertRoleResourceRelation" parameterType="RoleResourceRelation"> INSERT INTO role_resource(role_id,resource_id) VALUES(#{role_id},#{resource_id}) </insert>
6.用户和角色的绑定
<insert id="insertUserRoleRelation" parameterType="UserRoleRelation"> INSERT INTO user_role ( user_id, role_id) VALUE( #{userId}, #{roleId}) </insert>
总结:1.Controller层控制是否有权限@RequiresPermissions("role:view"),只要有这个标签,就是会走realm中的授权,这里面有我们在刚才登录时信息,从里面可以拿到我们的登录信息,获取到用户,然后从用户获取权限,将路径访问的方法 的role:view与数据库中的配置进行比较,没有匹配的将将会跳到无权显示中
2.前段设置权限显示:shiro会根据当前的用户的用户的权限和前段的字段进行比较,有匹配的就显示,没有的话就不显示
会自动走授权的方法!!不必纠结~
具体太细节的东西就不写了,因为要贴的东西太多了,这里是主要的配置,剩下的就是具体的代码了
每天进步一点点