Shiro框架详解

                在web开发过程中, 我们经常会碰到安全问题,哪些用户有权限访问,哪些用户没有权限访问,都是我们急需解决的.

  接下来介绍一下Shiro框架:

  一.Apache Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能:
           1)认证 - 用户身份识别,常被称为用户“登录”;

         2)授权 - 访问控制;

         3)密码加密 - 保护或隐藏数据防止被偷窥;

         4)会话管理 - 每用户相关的时间敏感的状态。

       对于任何一个应用程序,Shiro都可以提供全面的安全管理服务。并且相对于其他安全框架,Shiro要简单的多。


  二.Shiro的三个核心组件:Subject, SecurityManager 和 Realms

        1)Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。

          它仅仅意味着“当前跟软件交互的东西”。但考虑到大多数目的和用途,你可以把它认为是Shiro的“用户”概念。Subject代表了当前用户的安全操

          作,SecurityManager则管理所有用户的安全操作。

        2)SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。

        3)Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配

         置的Realm中查找用户及其权限信息。从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给

         Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。


  三. 环境配置:

      1)配置描述符文件(web.xml):  

    <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>

     2)配置文件shiro-config.xml :

        a. 添加ShiroFilter定义:

    <!-- Shiro Filter -->  
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
        <property name="securityManager" ref="securityManager" />
        <property name="loginUrl" value="/login.jsp" />
          <property name="successUrl" value="/success.jsp" /> 
        <property name="filterChainDefinitions">
            <value>
                /Login.action = anon
                /goLogin.action = anon
                /** = authc
             </value>
        </property>
    </bean>  

    b securityManager定义:

    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" >
	<property name="realm" ref="shiroRealm" />
	<property name="cacheManager" ref="cacheManager" />
    </bean>

       c.   添加自定义Realm:

     <!-- 項目自定义的Realm -->
     <bean id="shiroRealm" class="starview.common.account.service.ShiroRealm">//对应的类;
	<property name="isDebug">
	    <value>false</value>
	</property>	
	<property name="allPermissions">
		<list>
		   <value>program:list</value>
		   <value>program:edit</value>
		   <value>program:audit</value>
		   <value>DYBJ</value>
		   <value>DYSH</value>
		</list>
	</property>	
       </bean>

     四. 实现上述自定义的Realm:

 <span style="font-size:12px;">public class ShiroRealm extends AuthorizingRealm{
	private static Logger logger = Logger.getLogger(Logger.class);
	
	private String isDebug = "false";
	
	private List<String> allPermissions;

	/**
	 * 认证回调函数,登录时调用.
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException{
		logger.info("**********Enter the doGetAuthenticationInfo: 认证回调函数,登录时调用");
		try{
			UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
			String userName = token.getUsername();
			char[] pwd = token.getPassword();
	
			// 比较数据库中的用户名密码
			ShiroUser shiroUser = new ShiroUser(1L,userName,userName);
			return new SimpleAuthenticationInfo(shiroUser, pwd, userName);
		}catch(Exception err){
			logger.error("Failed to doGetAuthenticationInfo", err);
			return null;
		}
	}
	
	/**
	 * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用.
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		// TODO Auto-generated method stub
		try{
			logger.info("Enter the doGetAuthorizationInfo : 授权查询回调函数");
			ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
			String loginName = shiroUser.loginName;
			SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
			if("true".equalsIgnoreCase(isDebug)){//调试模式;
				logger.info("Enter the debug mode. allPermissions=" + allPermissions);
				//参数isDebug和allPermissions都是从shiro-config.xml文件传过来的,必须用get set方法才能获取;
				info.addStringPermissions(allPermissions);
				//自定义的shiro标签写入key里面;
				List<String> list = new ArrayList<String>();
				list.add("AAA");
				list.add("BBB");
				info.addStringPermissions(list);
			}
			else{//非调试模式;
				
				//从数据库中获取用户所用有的权限,放入info中;
				
			}	
			return info;
		}catch(Exception err) {
			logger.error("Failed to doGetAuthorizationInfo", err);
			return null;
		}

	}


	public String getIsDebug() {
		return isDebug;
	}

	public void setIsDebug(String isDebug) {
		this.isDebug = isDebug;
	}

	public List<String> getAllPermissions() {
		logger.info("*********allPermissions :" + allPermissions);
		return allPermissions;
	}

	public void setAllPermissions(List<String> allPermissions) {
		logger.info("*********allPermissions :" + allPermissions);
		this.allPermissions = allPermissions;
	}

	/**
	 * 自定义Authentication对象,使得Subject除了携带用户的登录名外还可以携带更多信息.
	 */
	public static class ShiroUser implements Serializable {
		private static final long serialVersionUID = -1373760761780840081L;
		public Long id;
		public String loginName;
		public String name;

		public ShiroUser(Long id, String loginName, String name) {
			this.id = id;
			this.loginName = loginName;
			this.name = name;
		}

		public String getName() {
			return name;
		}
}</span>
 

  五.登录部分:登录时候,如果认证通过,则调用此函数,之后会直接调用四中的认证回调函数
 <pre name="code" class="java">    public static final void setLogin(String userName, String userPassword) {

		Subject currentUser = SecurityUtils.getSubject();

		if (!currentUser.isAuthenticated()) {
			// collect user principals and credentials in a gui specific manner
			// such as username/password html form, X509 certificate, OpenID,
			// etc.
			// We'll use the username/password example here since it is the most
			// common.
			// (do you know what movie this is from? ;)
			UsernamePasswordToken token = new UsernamePasswordToken(userName,
					userPassword);
			// this is all you have to do to support 'remember me' (no config -
			// built in!):
			token.setRememberMe(true);
			currentUser.login(token);
		}
	}


 
   六.要在jsp中使用shiro框架,必须通过标签引入: 

      <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

 七.如何使用shiro标签:

  1)系统自带的标签:只要环境配置好之后,直接使用即可  

    <shiro:guest>  
    欢迎游客访问,<a href="${pageContext.request.contextPath}/login.jsp">登录</a>  
    </shiro:guest>   

   参考文档:http://jinnianshilongnian.iteye.com/blog/2026398

  2)自定义的一些标签:

   <shiro:hasPermission name="ADTPGL">
	<a target="myFrame" href="${basePath }/picture/picturelist.action" οnclick="setMenu(<%out.print(i);i++;%>);"><s:text name="menu.TPGL" /></a>
<span style="font-family:Monaco,'DejaVu sans Mono','Bitstream Vera sans Mono',Consolas,'Courier new',monospace;">   </span></shiro:hasPermission>
   像这种自定义的标签,我们必须把他的name值放入shiro的SimpleAuthorizationInfo中,也就是在四中的 授权查询回调函数 中使用:

   SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

   info.addStringPermissions("ADTPGL");

 八. 在七中,不管是自定义的标签还是系统本身自带的标签都被存放在了info当中,当访问一个页面时,页面上的每一个shiro标签都会自动在info

      当中查找相应的key值,如果查找到了,就有权限访问,如果没查找到,就无权限访问;

 九  
为了说明这篇文章,特意写了一个demo,大家可以去下载: 

http://download.csdn.net/detail/wangyi201212/8720311


十.效果图


附件:1.shrio 权限管理filterChainDefinitions过滤器配置 

http://www.cppblog.com/guojingjia2006/archive/2014/05/14/206956.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值