shiro安全框架

来源:互联网 发布:网络喷子现实就怂了 编辑:程序博客网 时间:2024/06/07 18:33

一:什么是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” %>

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

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

原创粉丝点击