配置shiro

什么是shiro

Apache Shiro是Java的一个安全框架。功能强大,使用简单的Java安全框架,它为开发人员提供一个直观而全面的认证,授权,加密及会话管理的解决方案。

准备工作

maven工程的配置

<!-- shiro -->
         <!-- apache shiro dependencies -->
         <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-all</artifactId>
            <version>${shiro.version}</version>
         </dependency>

web工程的导包
这里写图片描述

1. 在web.xml文件中的配置

  <!-- 注意:shiro的filter必须在struts2的filter之前,否则action无法创建 -->
    <!-- Shiro Security filter  filter-name这个名字的值将来还会在spring中用到  -->
<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>

注意:shiro的filter必须在struts2的filter之前,否则action无法创建

2. 在applicationContext.xml的配置

<!--Shiro安全框架产生代理子类的方式: 使用cglib方式,放在事务管理器之前配置-->
    <aop:aspectj-autoproxy proxy-target-class="true" />

注意:放在事务管理器之前配置

3.在applicationContext-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-3.0.xsd    
    http://www.springframework.org/schema/aop    
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd    
    http://www.springframework.org/schema/tx    
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd    
    http://www.springframework.org/schema/context    
    http://www.springframework.org/schema/context/spring-context-3.0.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="com.dml.bs.shiro.AuthRealm">
        <property name="userService" ref="userService"/>
        <!-- 自定义密码加密算法  -->
        <property name="credentialsMatcher" ref="passwordMatcher"/>
    </bean>

    <!-- 设置密码加密策略 md5hash -->
    <bean id="passwordMatcher" class="com.dml.bs.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>

注意:几处的修改
这里写图片描述

这里写图片描述

ehcache-shiro.xml
这里写图片描述
跳转的页面可以自行修改

4.ehcache-shiro.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="shiroCache">

    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            />
</ehcache>

5.加密算法

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

    public static void main(String[] args) {
        System.out.println(new Md5Hash("123456","tony",2).toString());
    }
}

6.AuthRealm

public class AuthRealm extends AuthorizingRealm{
    private UserService userService;

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    //授权 当jsp页面出现shiro标签时,就会执行授权方法
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection pc) {
        System.out.println("授权");
        User user = (User) pc.fromRealm(this.getName()).iterator().next();//根据realm的名字去找对应的realm

        Set<Role> roles = user.getRoles();//对象导航
        List<String> permissions = new ArrayList<>();
        for (Role role : roles) {
            //遍历每个角色
            Set<Module> modules = role.getModules();//得到每个角色下的模块列表
            for (Module module : modules) {
                permissions.add(module.getName());
            }
        }

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermissions(permissions);//添加用户的模块(权限)

        return info;
    }

    //认证 token代表用户在界面输入的用户名和密码
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("认证");

        //向下转型
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;

        //调用业务方法,实现根据用户名查询
        String hql = "from User where userName = ?";
        List<User> list = userService.find(hql, User.class, new String[]{upToken.getUsername()});
        if(list != null && list.size() >0){
            User user = list.get(0);
            AuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
            return info; //此处如果返回,就会立即进入密码比较器
        }

        return null;
    }

}

7.CustomCredentialsMatcher

public class CustomCredentialsMatcher extends SimpleCredentialsMatcher{

    //密码比较的方法 token代表用户在界面输入的用户名和密码 info代表从数据库中得到加密数据
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        //向下转型
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;

        //将用户在界面输入原始密码加密upToken.getPassword().toString()返回数组的首地址
        Object pwd = Encrypt.md5(new String(upToken.getPassword()), upToken.getUsername());

        //取出数据库中的加密密码
        Object dbPwd = info.getCredentials();
        return this.equals(pwd, dbPwd);
    }

}

LoginAction

public class LoginAction extends BaseAction {

    private static final long serialVersionUID = 1L;

    private String username;
    private String password;



    //SSH传统登录方式
    public String login() throws Exception {

//      if(true){
//          String msg = "登录错误,请重新填写用户名密码!";
//          this.addActionError(msg);
//          throw new Exception(msg);
//      }
//      User user = new User(username, password);
//      User login = userService.login(user);
//      if (login != null) {
//          ActionContext.getContext().getValueStack().push(user);
//          session.put(SysConstant.CURRENT_USER_INFO, login);  //记录session
//          return SUCCESS;
//      }
//      return "login";

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

        try {
            //1.得到Subject
            Subject subject = SecurityUtils.getSubject();
            //2.调用登录方法
            UsernamePasswordToken token = new UsernamePasswordToken(username, password);
            //当这行代码执行时,就会进入密码比较器
            subject.login(token);

            //3.登录成功时,就从Shiro中取出用户的登录信息
            User user = (User) subject.getPrincipal();

            //4.将用户放入设施上域中
            session.put(SysConstant.CURRENT_USER_INFO, user);
        } catch (Exception e) {
            e.printStackTrace();
            request.put("errorInfo", "对不起,用户名或密码错误!");
            return "login";
        }

        return SUCCESS;
    }


    //退出
    public String logout(){
        session.remove(SysConstant.CURRENT_USER_INFO);      //删除session

        return "logout";
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}

登陆后的页面加上如下代码,就会执行授权

 <!-- 当jsp页面碰到shiro标签时就执行AuthRealm中授权方法 -->
    <shiro:hasPermission name="系统首页">
    <span id="topmenu" onclick="toModule('home');">系统首页</span><span id="tm_separator"></span>
    </shiro:hasPermission>

    <shiro:hasPermission name="系统管理">
    <span id="topmenu" onclick="toModule('sysadmin');">系统管理</span>
    </shiro:hasPermission>

    <shiro:hasPermission name="素质学分任务管理">
        <span id="topmenu" onclick="toModule('cargo');">素质学分任务管理</span><span id="tm_separator"></span>
    </shiro:hasPermission>

    <shiro:hasPermission name="学生任务管理">
    <span id="topmenu" onclick="toModule('baseinfo');">学生任务管理</span><span id="tm_separator"></span>
    </shiro:hasPermission>

    <shiro:hasPermission name="素质学分任务审核">
    <span id="topmenu" onclick="toModule('stat');">素质学分任务审核</span><span id="tm_separator"></span>
    </shiro:hasPermission>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值