shiro学习总结(一)

来源:互联网 发布:mac 视频截取gif 编辑:程序博客网 时间:2024/05/19 15:45

shiro学习总结(一)

一、shiro简介
  shiro是Java的一个安全(权限框架)。
  shiro可以完成:认证、授权、加密、会话管理、与web集成、缓存等;
  最主要的四个功能:认证(如密码匹配)、授权、会话管理、加密;
  Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。但考虑到大多数目的和用途,你可以把它认为是Shiro的“用户”概念。
  Subject代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
  SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
  Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。
二、HelloWorld
 shiroFilter是一个入口;
 anon 拦截器表示匿名访问,既不需要登录即可访问;
 authc 拦截器表示需要身份认证通过后才能进行访问;
 logout 表示登出的过滤器
 没有配置成 authc 的可以进行访问;配置成 anon 匿名的可以进行访问;

<property name="filterChainDefinitions">  <value>   /login.jsp = anon   /** = authc </value></property>

  在 applicatioContext.xml 中配置的 org.apache.shiro.spring.web.ShiroFilterFactoryBean 的名字必须和 web.xml 中的 org.springframework.web.filter.DelegatingFilterProxy 的名字相同;若不一致,则会在加载项目时抛出
org.springframework.beans.factory.NoSuchBeanDefinitionException 异常,因为 shiro 会在 IOC 容器中 查找和 <filter-name> 相同的对象的bean(也可以通过 targetBeanName 这个参数配置);
  DelegatingFilterProxy 实际上是 Filter 的一个代理对象,默认情况回到 IOC 容器中查找和 <filter-name>对应的filter bean,也可以通过 targetBeanName 的初始化参数来配置 filter bean 的id;
URL 匹配模式使用 Ant 风格模式:
?:匹配一个字符;
*:匹配零个或多个字符;
**:匹配路径中的另个或多个路径;
URL匹配采用第一匹配优先的模式;

shiro认证:
  1. 获取当前的Subject,调用 SecurityUtils.getSubject();
  2.测试当前的用户是否已经被认证,即是否已经登录, 调用 Subject 的 isAuthenticates()
  3.若没有被认证,则把用户名和密码封装为 UsernamePasswordToken对象;
   1).创建一个表单页面
   2).把请求提交到 SpringMVC的Handler
   3).获取用户名和密码
  4.执行登录:调用Subject 的login(AuthenticationToken )方法。
  5.自定义 Realm 的方法,从数据库中获取对应的记录,返回给 shiro;
  1).实际上需要继承 org.apache.shiro.realm.AuthenticatingRealm 类
  2).实现doGetAuthenticationInfo(AuthenticationToken) 方法。
  6.由 shiro 完成对密码的比对。

自定义Realm:

package com.vincent.shiro.realms;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.LockedAccountException;import org.apache.shiro.authc.SimpleAuthenticationInfo;import org.apache.shiro.authc.UnknownAccountException;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.realm.AuthenticatingRealm;public class ShiroRealm extends AuthenticatingRealm{    @Override    protected AuthenticationInfo doGetAuthenticationInfo(            AuthenticationToken token) throws AuthenticationException {        //1、把 AuthenticationToken 转换为 UsernamePasswordToken        UsernamePasswordToken upToken = (UsernamePasswordToken) token;        //2、从 UsernamePasswordToken 中获取 username        String username = upToken.getUsername();        //3、调用数据库的方法,从数据库中查询 username 对应的用户记录        System.out.println("从数据库中获取username:"+username+" 所对应的用户信息。");        //4、若用户不存在,则可以抛出 UnknownAccountException 异常        if("unknown".equals(username)){            throw new UnknownAccountException("用户不存在");        }        //5、根据用户信息的情况,决定是否需要抛出其他的 AuthenticationException 异常        if("monster".equals(username)){            throw new LockedAccountException("用户被锁定");        }        //6、根据用户的情况,来构建 AuthenticationException 对象并返回。通常使用的实现类为:SimpleAuthencationInfo        //以下信息是从数据中获取的        //(1)、principle:认证的实体信息,可以是username,也可以是数据表对应的用户的实体类对象.         Object principal = username;         //(2)、credentials:从数据表中获取的密码         Object credentials = "123456";         //(3):realmName:当前 realm 对象的 name,调用父类的 getName()  方法即可         String realmName = getName();         SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, realmName);        return info;    }}

tips:由于存在shiro 缓存,因此需要在登录成功后需要执行登出操作才能测试其他效果;

密码的比对:
 通过 AuthenticationRealm 的credentialsMatcher 属性来进行的密码的比对!可以通过 credentialsMatcher 来进行密码的加密。
密码的加密(MD5加密、SHA1加密):
 在数据库中保存的密码不应该是明文,而且加密操作应该是不可逆的;
 1)、如何把一个字符串加密为 MD5(对从数据库中获取的字符串进行加密);
 2)、替换当前 Realm 的credentialsMatcher 。直接使用HashedCredentialsMatcher 对象,并设置属性加密算法即可(用于把从前台获取的密码进行 MD5 加密);
 

 <bean id="jdbcRealm" class="com.vincent.shiro.realms.ShiroRealm">        <property name="credentialsMatcher">            <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">                <property name="hashAlgorithmName" value="MD5"></property>            </bean>        </property>    </bean>

  密码的MD5盐值加密(salt)
  密码的MD5加密存在的问题:如果两人使用的密码一样,则加密后的结果将会一样;
  步骤:
  1):在 doGetAuthenticationInfo 方法返回值创建 SimpleAuthenticationInfo 对象时,需要使用如下构造器:

 new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName)

  2)、使用 ByteSource.Util.bytes() 计算盐值;
  3)、盐值需要唯一:一般使用随机字符串或 user id;
  4)、使用 new SimpleHash(algorithmName, source, salt, iterations); 来计算盐值加密后的密码的值;
  使用以上方法,即使两个人使用同样的密码,数据库中保存的密码也不相同;
 
多Realm:
  配置流程:
 

 <bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">        <property name="realms">            <list>                <ref bean="jdbcRealm"/>                <ref bean="secondRealm"/>            </list>        </property>   </bean> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">        <property name="cacheManager" ref="cacheManager"/>        <!-- Single realm app.  If you have multiple realms, use the 'realms' property instead. -->        <property name="authenticator" ref="authenticator"/>    </bean>

  多个realm是有认证顺序的;

原创粉丝点击