shiro实战经验与搭建所需资源

        最近公司需要增加角色权限管理模块,由我负责开发,经过慎重考虑,我舍弃了自己写一个权限管理框架的傻叉想法(还当上学呢),而是用了开源的shiro去实现。由于经验不足,搞了几天才弄懂,终于也算是搭建上了,实现了角色权限管理,大白话就是能校验登录信息是否正确,根据数据库给用户赋予角色,登录后根据角色展示不同的模块信息。但是不足的是,由于需求没要求,也是自己没搞定,就是我现在无法给角色分配权限,权限可以分配到用户上,所以权限和角色就成了一个平行的关系(但事实上应该不是这样),还有待研究,有经验的大牛可以给小弟指点指点,不胜感激。

       言归正传,搭建框架第一步要有相应的资源,感谢资源提供者【尚硅谷教育】。链接: http://pan.baidu.com/s/1sjvJtJR 密码: 47c3,百度云盘,上面有详细的视频和例子,jar包。我基本就是看着这个视频搭建的(也借助了网上很多文章和demo项目)。但是,要只看视频就ok的话,这篇博客就到此为止了,但下面才是我在搭建时遇见的各种问题,以及我解决问题的思路和方法,甚至有些问题依然没有解决,我只是绕过了他实现了需求。follow my thought。

      先把基础的搭建说下吧(用spring管理shiro配置方案):

首先在web.xml里面完成spring基础配置,然后配置Shiro的FilFilter

    <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>
然后在classpath下创建shiro自己的配置文件
<?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"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd 
		http://www.springframework.org/schema/mvc
       	http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
		">
	<!-- 配置缓存管理器 -->
	<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
		<!-- 指定ehcache的配置文件 -->
		<property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/>
	</bean>
	
	<!-- 配置进行授权和认证的realm -->
	<bean id="myRealm"
		class="com.atguigu.shiro.realm.MyRealm"></bean>
	
	<!--配置shiro的securityManager Bean  -->	
	<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="cacheManager" ref="cacheManager"/>
        <property name="realm" ref="myRealm"/>
    </bean>
    
    <!-- 配置bean 后置处理器 :会自动调用和spring整合后各个组件的生命周期方法-->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    
    <!-- 配置ShiroFilter bean:该bean的id必须和web.xml文件中filter的name一致 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    	<!-- 装配 securityManager-->
        <property name="securityManager" ref="securityManager"/>
        <!-- 配置登录页面 -->
        <property name="loginUrl" value="/shiro-login.jsp"/>
        <!-- 登录成功之后的页面 -->
        <property name="successUrl" value="/shiro-success.jsp"/>
        <!-- 授权失败页面 -->
        <property name="unauthorizedUrl" value="/unauthorized.jsp"/>
        <!-- 具体配置需要拦截哪些URL,以及访问对应的URL时 -->
        <property name="filterChainDefinitions">
        <!-- anon表示 可以 匿名登录 -->
        <!-- authc表示 需要认证(登录)才能使用  -->
        <!-- roles 角色过滤器,判断当前用户是否指定角色 -->
            <value>
            	/shiro-logout = logout
                /shiro-* = anon
                <!-- /user.jsp = roles[user] -->
                /user.jsp = perms[userCm]
                <!-- /admin.jsp = roles[admin] -->
                /admin.jsp = perms[adminCm]
                /** = authc
            </value>
        </property>
    </bean>
</beans>

还有spring、springmvc和ehcache的配置文件就不在这里列出了,稍后我会给出github源码链接,我自己完善好的代码。

然后我们需要创建一个类去继承AuthorizingRealm,实现doGetAuthorizationInfo(授权)和doGetAuthenticationInfo(认证)方法。

在controller中这样写,执行login时就自动调用认证和授权方法了,认证即比对输入的账号密码与数据库的是否一致,授权就是根据数据库分配给用户相应的角色权限

<span style="white-space:pre">	</span>Subject subject = SecurityUtils.getSubject();
<span style="white-space:pre">	</span>UsernamePasswordToken token = new UsernamePasswordToken(username,password);

<span style="white-space:pre">	</span>subject.login(token);
下面讲下授权与认证方法怎么写

<span style="white-space:pre">	</span>/**
	 * 认证方法
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		System.out.println("-----进入认证方法----by:cuimiao demo");
		//登录的主信息:从数据库中查询的结果,该结果和token中携带的必须一致
		String principal = (String) token.getPrincipal();
		//认证信息:从数据库中查询出来的信息。密码的比对交给shiro去进行比较
		String credentials = "123456";
		//当前realm的name
		String realmName = getName();
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, realmName);
		System.out.println("-----认证方法结束----by:cuimiao demo");
		return info;
	}
很神奇的是执行subject.login(token);的时候就调用了认证方法,认证通过后就带着info调用授权方法
<span style="white-space:pre">	</span>/**
	 * 授权方法
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
		System.out.println("-----进入授权方法----by:cuimiao demo");
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		
		Object principal = principalCollection.getPrimaryPrincipal();
		
		if("admin".equals(principal)){
//			info.addRole("admin");
			info.addStringPermission("adminCm");
		}
		if("user".equals(principal)){
//			info.addRole("test");
			info.addStringPermission("testCm");
		}
//		info.addRole("user");
		info.addStringPermission("userCm");
		System.out.println("-----授权方法结束----by:cuimiao demo");
		return info;
	}

我们可以把在数据库的相应的权限放到info中,然后info会带着这权限,每次进入页面时检测shiro配置文件,判断该权限是否可以登录该页面。

然后前端jsp上引用标签<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>,然后

<span style="white-space:pre">	</span><shiro:hasAnyRoles name="user">
		<a href="user.jsp">User Page</a>
	</shiro:hasAnyRoles>
就可以判断 只有user角色可以访问<a href="user.jsp">User Page</a>这个链接了。

大体流程就是这样了。


首先第一个坑是springMVC配置文件编译不通过,查了多方资料后发现是jar包有问题,我把spring的jar包重新下了一份,导入后解决问题。

第二个坑是demo中执行subject.login(token)时都自动调用授权方法,但在正式项目中,死活都不走授权,只走认证,多方查找资料,有的说是缓存原因,有的说是配置原因,具体什么原因我没查出来,诸位网友可以踩在我的肩膀上帮我看看是因为什么(稍后我会提供两个demo,一个是自动走授权的,一个是不自动走的)。如果解决了,告诉老兄,不胜感激!(联系方式-微信:cuimiao147)

那解决不了不能不授权啊,我就选择了一个最笨的法,虽然也解决了问题,但不知道是否后期有隐患。

就是手动显式的调用授权方法,但由于授权方法是protected的,所以我需要对它稍微加工下

<span style="white-space:pre">	</span>public void doGetAuthorizationInfoByAdmin(PrincipalCollection principalCollection) {
		this.doGetAuthorizationInfo(principalCollection);
	}
这样我们就可以在subject.login(token);执行结束后手动调用授权方法了,调用的代码是
testRealm.doGetAuthorizationInfoByAdmin(subject.getPrincipals());
把他们放在一个try块中,认证不通过时就抛异常不执行授权方法了,通过时则会给用户授权。

github链接:

可用demo,会自动调用授权方法,不带数据库

网上demo,不自动调用授权方法,带数据库脚本(网友们寻找原因哈)

    

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值