shiro安全框架

一:什么是Shiro?
它是一个安全框架,用于解决系统的认证和授权问题,同时提供了会话管理,数据加密机制。
二.应用程序如何使用Shiro框架?
这里写图片描述

可以看出,程序员只关注两部分:
1.如何获得Subject
2.如何定义一个符合规定的Realm域(密码比较器的定义也是程序员干的)

三.具体步骤:
1.导入jar包
Maven工程

    <dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-all</artifactId>
        <version>1.2.3</version>
</dependency>

Web工程
这里写图片描述

2.过滤器的配置
这里写图片描述

3.产生代理类的方式
下面这一行代码,放在applicationContext.xml事务管理器声明之前

 <aop:aspectj-autoproxy proxy-target-class="true" />

4.Shiro的配置文件application-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:p="http://www.springframework.org/schema/p"  
    xmlns:context="http://www.springframework.org/schema/context"   
    xmlns:tx="http://www.springframework.org/schema/tx"  
    xmlns:aop="http://www.springframework.org/schema/aop"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans    
    http://www.springframework.org/schema/beans/spring-beans.xsd    
    http://www.springframework.org/schema/aop    
    http://www.springframework.org/schema/aop/spring-aop.xsd    
    http://www.springframework.org/schema/tx    
    http://www.springframework.org/schema/tx/spring-tx.xsd    
    http://www.springframework.org/schema/context    
    http://www.springframework.org/schema/context/spring-context.xsd">

    <description>Shiro的配置</description>

    <!-- SecurityManager配置 -->
    <!-- 配置Realm域 -->
    <!-- 密码比较器 -->
    <!-- 代理如何生成? 用工厂来生成Shiro的相关过滤器-->
    <!-- 配置缓存:ehcache缓存 -->
    <!-- 安全管理 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!-- Single realm app.  If you have multiple realms, use the 'realms' property instead. -->
        <property name="realm" ref="authRealm"/><!-- 引用自定义的realm -->
        <!-- 缓存 -->
        <property name="cacheManager" ref="shiroEhcacheManager"/>
    </bean>

    <!-- 自定义权限认证 -->
    <bean id="authRealm" class="cn.itcast.jk.shiro.AuthRealm">
        <property name="userService" ref="userService"/>
        <!-- 自定义密码加密算法  -->
        <property name="credentialsMatcher" ref="passwordMatcher"/>
    </bean>

    <!-- 设置密码加密策略 md5hash -->
    <bean id="passwordMatcher" class="cn.itcast.jk.shiro.CustomCredentialsMatcher"/>

    <!-- filter-name这个名字的值来自于web.xml中filter的名字 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <!--登录页面  -->
        <property name="loginUrl" value="/index.jsp"></property>
        <!-- 登录成功后 -->      
        <property name="successUrl" value="/home.action"></property>
        <property name="filterChainDefinitions">
            <!-- /**代表下面的多级目录也过滤 -->
            <value>
                /index.jsp* = anon
                /home* = anon
                /sysadmin/login/login.jsp* = anon
                /sysadmin/login/logout.jsp* = anon
                /login* = anon
                /logout* = anon
                /components/** = anon
                /css/** = anon
                /images/** = anon
                /js/** = anon
                /make/** = anon
                /skin/** = anon
                /stat/** = anon
                /ufiles/** = anon
                /validator/** = anon
                /resource/** = anon
                /** = authc
                /*.* = authc
            </value>
        </property>
    </bean>

    <!-- 用户授权/认证信息Cache, 采用EhCache  缓存 -->
    <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/>
    </bean>

    <!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

    <!-- 生成代理,通过代理进行控制 -->
    <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>

5.在applicationContext.xml文件中加载shiro配置文件

   <import resource="classpath:spring/applicationContext-shiro.xml"></import>

6.编写密码比较器
1. 替换原有的utils工具包中的类
2. Md5Hash算法介绍

//高强度加密算法,不可逆
    public static String md5(String password, String salt){
        return new Md5Hash(password,salt,2).toString();
    }

3.密码比较器

public class CustomCredentialsMatcher extends SimpleCredentialsMatcher {

    /**
     * 执行密码比较的方法
     * 如果返回true,证明密码比较成功
     *         false,证明密码比较失败
     *         
     *         AuthenticationToken token:代表用户在界面上输入的用户名和密码
     *         AuthenticationInfo:它可以保存用户在数据库中的密文
     */
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        //1.向下转型
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;

        //2.得到原始密码,没有的密码,
        String oldPwd = new String(upToken.getPassword());

        //3.并进行加密
        String newPwd = Encrypt.md5(oldPwd, upToken.getUsername());

        //4.获取数据库中当前用户的密文
        Object dbPwd = info.getCredentials();

        return equals(newPwd, dbPwd);
    }

}

7.编写自定义Realm域

public class AuthRealm extends AuthorizingRealm {

    private UserService userService;//注入业务逻辑
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    //授权  当jsp页面上读取到shiro标签时,就会执行这个方法
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        System.out.println("授权");
        //1.通过指定realm域的名字,找到之前放进去的principal值,这个值 就是用户对象
        User user = (User) principal.fromRealm(this.getName()).iterator().next();

        List permissions = new ArrayList();

        //2.数据加载
        Set<Role> roles = user.getRoles();//通过关联级别的数据加载,得到当前用户的所有角色
        for(Role role :roles){
            //遍历每个角色
            Set<Module> modules = role.getModules();//再次使用关联级别数据检索,来加载当前角色下的模块(权限)
            for(Module m:modules){
                permissions.add(m.getCpermission());//组织权限字符串
            }
        }

        //返回值
        SimpleAuthorizationInfo sAuthInfo = new SimpleAuthorizationInfo();
        sAuthInfo.addStringPermissions(permissions);
        return sAuthInfo;
    }

    //认证  (登录)
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {
        System.out.println("认证");
        //1.转化token
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;

        //2.调用业务方法,进行查询
        List<User> list = userService.find("from User u where u.userName=?" , User.class, new Object[]{upToken.getUsername()});//根据用户名得到一个用户对象
        User user = null;
        if(list!=null && list.size()>0){
            user = list.get(0);
        }


        return new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
    }

}

8.登录操作

if(UtilFuns.isEmpty(username)){
            return "login";
        }

        //使用Shiro实现登录操作

        try {
            //1.得到Subject对象
            Subject subject = SecurityUtils.getSubject();


            //2.封装用户数据成一个AuthenicationToken对象
            UsernamePasswordToken uptoken =  new UsernamePasswordToken(username, password);
            //3.实现登录操作
            subject.login(uptoken);  //立即调用AuthRealm域中的认证方法

            //4.登录成功后,就可以从Shiro中取出用户对象
            User user = (User)subject.getPrincipal();


            //因为这些数据,在多处要使用,所以懒加载没有优势,所以提前加载出来,这样在多处使用时就不需要加载了
            System.out.println(user.getDept().getDeptName());
            Set<Role> roles = user.getRoles();//通过关联级别的数据加载,得到当前用户的所有角色
            for(Role role :roles){
                //遍历每个角色
                System.out.println(role.getName());
                Set<Module> modules = role.getModules();
                for(Module m:modules){
                    System.out.println(m.getCpermission());
                }
            }

            //5.将用户信息,放入session域中
            session.put(SysConstant.CURRENT_USER_INFO, user);
        } catch (Exception e) {
            e.printStackTrace();
            //当密码比较失败后,也会抛出异常
            request.put("errorInfo", "对不起,用户名或密码错误,登录失败");
            return "login";
        }
        return SUCCESS;
    }

9.jsp
当jsp页面上出现Shiro标签时就会执行AuthRealm域中的授权方法。
1.引入Shiro标签
<%@ taglib uri=”http://shiro.apache.org/tags” prefix=”shiro” %>

登录过程:
这里写图片描述

授权的过程:
这里写图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值