ssm搭建shrio安全框架(动态加载)

ssm搭建shrio安全框架(动态加载)

描述:
下面实现例子,实现简单,权限只控制到模块,模块勾选,模块下的功能全部通过。
其实要控制到方法,只需要添加一些标记字符即可。

一、 shrio介绍
二、导入jar包
三、Web.Xml配置
四、Shrio.xml 配置
五、重点实现shiro配置的内容(必须)
六、根据需求实现shiro配置
七、java文件和配置下载


一、shrio简单介绍

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
框架图:
这里写图片描述

1、Subject:当前操作用户
2、SecurityManager :安全管理器,Shiro框架的核心组件,管理所有Subject。
内部组成:

      Authenticator(登录认证)。
      Authorizer(访问授权)。
      Session Manager(创建和管理用户Session生命周期)。
      Session Dao(操作session数据,可重写AbstractSessionDAO对 
                   session实现增删查改操作)。
      CacheManager(缓存Shiro使用的鉴权数据)。

3、Realms:领域,用于进行权限信息的验证(实现Authenticator和Authorizer)

详细解析参考其他博客。

二、导入jar包

        版本号
        <shiro.version>1.3.2</shiro.version>
<!—shiro相关jar包 -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>${shiro.version}</version>
        </dependency>

三、Web.Xml配置

<filter>
        <!--与shiro.xml里org.apache.shiro.spring.web.ShiroFilterFactoryBean的bean 
            name相同 -->
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

四、Shrio.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:jee="http://www.springframework.org/schema/jee"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd"
    default-lazy-init="true">


    <!-- Shiro 拦截 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- shiro的核心安全接口 -->
        <property name="securityManager" ref="securityManager" />
        <!-- 登录时的链接 -->
        <property name="loginUrl" value="/jsp/login.jsp" />
        <!-- 登录成功时,跳转的链接 -->
        <property name="successUrl" value="/jsp/Main.jsp" />
        <!-- 未认证时跳转的链接 -->
        <!-- <property name="unauthorizedUrl" value="/jsp/login.jsp" /> -->


        <property name="filters">
            <!-- 添加链接key规则,系统默认key有:anon(无需权限),authc(登录后可访问),perms(需要指定的权限),roles(需要指定角色)等,还可以自定义key -->
            <map>
                 <!--系统默认key-->
                <entry key="authc">
                    <bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter" />
                </entry>
                <!--重写perms-->
                <entry key="perms">
                     <!--继承PermissionsAuthorizationFilter进行重写-->
                    <bean class="重写权限类"></bean>
                </entry>
                <!--自定义key
                <entry key="填写自定义key">
                    <bean class="指向指定类"></bean>
                </entry>
                -->
            </map>
        </property>
        <!--配置拦截链接-->
        <property name="filterChainDefinitionMap" ref="chainDefinitionSectionMetaSource" />
    </bean>
     <!--加载拦截链接-->
    <bean id="chainDefinitionSectionMetaSource" class="拦截连接实现类"></bean>

    <!-- 安全接口 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="userAuthorization" />
    </bean>

    <!-- 登录认证、授权 -->
    <bean id="userAuthorization" class="登录授权认证实现类">

    </bean>

    <!-- 使用springmvc HandlerExceptionResolver接口处理shiro异常 -->
    <bean class="异常拦截"></bean>
</beans>

五、重点实现shiro.xml配置的内容(必须)

(1)实现AuthorizingRealm类(登录授权认证实现类)

实现shiro.xml中配置

    <!-- 登录认证、授权 -->
    <bean id="userAuthorization" class="登录授权认证实现类">

doGetAuthorizationInfo 访问需要权限链接时进入(授权)

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pCollection) {
        //用户授权 
String userName = SecurityUtils.getSubject().getPrincipal().toString();
        if (!StringUtils.isEmpty(userName)) {
              //获取用户权限字符串
            String[] actionList ={};
            for (String str : actionList) {
                //设置用户权限
                info.addStringPermission(str);
            }
            //返回权限信息
            return info;
        }
        return null;
}

doGetAuthenticationInfo 用户登录时进入(验证)

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //用户认证
UsernamePasswordToken uPasswordToken = (UsernamePasswordToken) token;
String userName = uPasswordToken.getUsername();
        char[] c = uPasswordToken.getPassword();
        if (userName == null || userName.equals("") || c == null ||c.length==0) { 
//用户名或密码为空,直接退出
            return null;
}
        //这里查询用户,处理业务需求 
UserAuthority userAuthority=new UserAuthority();
         userAuthority.setUserName(“aaa”);
         SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userAuthority, passwork,getName());
        return info;
}

UserAuthority 类解释
定义所需保存的数据(根据自己需求定义一个类即可)

如何doGetAuthenticationInfo登陆验证

public Object login(String userName, String passwork) {
           //获取主体
        Subject subject=SecurityUtils.getSubject();
        AuthenticationToken token=new UsernamePasswordToken(username, password);
        //开始认证
        subject.login(token);
        //获取用户认证
        boolean bool=subject.isAuthenticated();
        System.out.println("认证成功:"+bool);
        ModelAndView mv = new ModelAndView();
        if (bool) {
            return "redirect:/jsp/Main.jsp";
        } else {
            return "redirect:/jsp/login.jsp";
        }
 }

当前台点击登录时,访问login方法,获取主体,并设置用户密码令牌,当代码执行到
subject.login(token)时触发doGetAuthenticationInfo方法,并得到的令牌AuthenticationToken ,因为得到的令牌是登录时设置的用户密码令牌,因此将该令牌token转回UsernamePasswordToken。接着查询数据库获取用户,并将查询到的用户信息设置到SimpleAuthenticationInfo,并返回SimpleAuthenticationInfo。紧接着继续执行subject.login(token)后的方法。

(2)设置整个系统的所有权限

实现shrio.xml中的

<!--加载拦截链接-->
<bean id="chainDefinitionSectionMetaSource" class="拦截连接实现类"></bean>
利用spring的FactoryBean<Ini.Section>动态获取数据库保存的链接,
实现方法getObject(),该方法会在spring容器加载时触发。
private StringBuffer filter = new StringBuffer();

public static final String PREMISSION_STRING = " = authc,perms[\"{0}\"]\n";

public Section getObject() {
        //添加字符串格式:url=key,如url=authc,perms["权限字符串"]
        filter.append("/jsp/login.jsp=anon\n");//这里\n必须写上,防止拼接成一行,导致Ini.Section解释成一条链接
        //这里完成权限字符串获取,拼接(数据库查询)
        filter.append("");
        Ini ini = new Ini();
        ini.load(fiter);
        Ini.Section section = ini.getSection(Ini.DEFAULT_SECTION_NAME);
        return section;
}

为什么使用类Ini.Section?

从org.apache.shiro.spring.web.ShiroFilterFactoryBean类中,
可以看出filterChainDefinitionMap属性的类型是Map<String,String>,
因此继承FactoryBean<>的泛型必须为Map<String,String>或者它的子类,
Ini.Section是shrio对Map<String,String>的封装,
也可以写成FactoryBean<Map<String,String>>,
key为url,value为权限字符(authc,perms["权限字符串"])

ShiroFilterFactoryBean类
这里写图片描述
Ini.Section类
这里写图片描述

六、根据需求实现shiro配置

剩下Shrio.xml中没实现的就是按自己需求来配置

(1)PermissionsAuthorizationFilter重写(权限字符串重写)

重写shrio.xml中的

引入重写内容,在shiro拦截器中加入filters属性
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="filters">
        <map>
            <entry key="perms">
                <bean class="重写权限类"></bean>
            </entry>
        </map>
    </property>
</bean>

原来的拦截方式:
(如果长度为1,判断是否有改权限字符串,长度不为1判断是否拥有所有的权限字符串,
如:/url= authc,perms[“12”,”21”],当访问/url时,就必须拥有”12”,”21”,这两个字符串)

public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
        Subject subject = getSubject(request, response);
        String[] perms = (String[]) mappedValue;
        boolean isPermitted = true;
        if (perms != null && perms.length > 0) {
            if (perms.length == 1) {
                if (!subject.isPermitted(perms[0])) {
                    isPermitted = false;
                }
            } else {
                if (!subject.isPermittedAll(perms)) {
                    isPermitted = false;
                }
            }
        }
        return isPermitted;
}

重写后的拦截方式(只需判断是否拥有其中一个权限字符串就可以访问,
如/url= authc,perms[“12”,”21”],当访问/url时,拥有”12”或”21”就可以访问 )

 public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
        Subject subject = getSubject(request, response);
        String[] perms = (String[]) mappedValue;
        if (perms != null && perms.length > 0) {
            boolean[] bs = subject.isPermitted(perms); //返回判断数组
             for (boolean b : bs) {
                if(b){ 
                    //说明有权限,直接返回                    
return true;
                }
         }
        }
        return false;
}

(2)异常拦截

重写shiro.xml配置文件

引入重写内容,在shiro.xml文件,直接追加bean
<!-- 使用springmvc HandlerExceptionResolver接口处理shiro异常 -->
<bean class="异常拦截"></bean>
   当访问链接时出现异常如何处理

实现springmvc的HandlerExceptionResolver异常处理

public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object object,Exception ex){
    ex.printStackTrace();
    if(ex instanceof UnauthorizedException) {  
        //没有认证
        System.out.println("没有认证");
        ModelAndView mv = new ModelAndView("redirect:/jsp/login.jsp");
         return mv;  
     }else if(ex instanceof UnknownAccountException||ex instanceof AuthenticationException) {  
            //登录过期没有权限  跳回登录页面
            System.out.println("登录过期");
            ModelAndView mv = new ModelAndView("redirect:/jsp/login.jsp");
            mv.addObject("Result", "您需要登录");
        return mv;
     } else if(ex instanceof HostUnauthorizedException){
             System.out.println("没有接口权限");
          return new ModelAndView("exception/noPermission");  
     }
        return null;  
}

标题1中介绍的SecurityManager 剩下内容

  Session Manager(创建和管理用户Session生命周期)。
  CacheManager(缓存Shiro使用的鉴权数据)。

如有需要继续往下面配置中添加即可。

    <!-- 安全接口 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="userAuthorization" />
        <!--需要添加-->
    </bean>

这里就不配置了。

七、java文件和配置下载

文件下载

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章