shiro框架的使用

Posted super超人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shiro框架的使用相关的知识,希望对你有一定的参考价值。

基于ssm框架:

1.引入shiro相关jar包:

shiro-core-1.2.3.jar

shiro-ehcache-1.2.3.jar

shiro-quartz-1.2.3.jar

shiro-spring-1.2.3.jar

shiro-web-1.2.3.jar

2.配置applicationContext-shiro.xml(/WEB-INF/conf/applicationContext-shiro.xml):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <description>apache shiro配置</description>

    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
       <!--  <property name="loginUrl" value="/index2.jsp"/>
        <property name="successUrl" value="/main/main.htm"/>
        <property name="unauthorizedUrl" value="/page/401.htm"/> -->
        <property name="filterChainDefinitions">
            <value>
                <!-- 静态资源允许访问 -->
                <!-- /** = anon -->
                <!-- /app/** = anon
                /assets/** = anon -->
                <!-- 登录页允许访问 -->
               <!--  /user/login.htm = anon -->
                
                /test111/loginAdmin.html=anon
                <!-- 其他资源需要认证 -->
                /** = authc
            </value>
        </property>
    </bean>

    <!-- 缓存管理器 使用Ehcache实现 -->
    <!-- 
    <bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager" p:cacheManagerConfigFile="/WEB-INF/conf/ehcache-shiro.xml">
    </bean>
     -->
    <!-- 会话DAO -->
    <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO"/>

    <!-- 会话管理器 -->
    <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <property name="sessionDAO" ref="sessionDAO"/>
    </bean>

    <!-- 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realms">
            <list>
                <ref bean="securityRealm"/>
            </list>
        </property>
        <!-- cacheManager,集合spring缓存工厂 -->
        <!-- <property name="cacheManager" ref="shiroEhcacheManager" /> -->
        <!-- <property name="sessionManager" ref="sessionManager" /> -->
    </bean>

    <!-- Shiro生命周期处理器 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

</beans>

3.配置缓存文件:ehcache-shiro.xml(/WEB-INF/conf/ehcache-shiro.xml)

<ehcache updateCheck="false" name="shiroCache">

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

4.web.xml配置shiro:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
            /WEB-INF/conf/applicationContext.xml
            /WEB-INF/conf/applicationContext-shiro.xml
            classpath*:applicationContext.xml
        </param-value>
  </context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

<!-- shiro 安全过滤器 -->
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <async-supported>true</async-supported>
        <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>

5.java代码:
建立applicationContext-shiro.xml中引用到的类securityRealm:

package com.test.www.web.security;

import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;

import com.test.www.web.entity.user.User;

/**
 * 用户身份验证,授权 Realm 组件
 * 
 **/
@Component(value = "securityRealm")
public class SecurityRealm extends AuthorizingRealm {
    /**
     * 权限检查
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        /*SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        String username = String.valueOf(principals.getPrimaryPrincipal());

        System.out.println("ssssssss");*/
        //String username = principals.getPrimaryPrincipal().toString() ;
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo() ;
        /*Set<String> roleName = t_userService.findRoles(username) ;
        Set<String> permissions = t_userService.findPermissions(username) ;*/
        //角色集合
        Set<String> roleName = new HashSet<String>(); 
        //权限集合
        Set<String> permissions = new HashSet<String>();
        roleName.add("admin");
        permissions.add("pub:coursecategory");
        authorizationInfo.setRoles(roleName);
        authorizationInfo.setStringPermissions(permissions);

        return authorizationInfo;
    }

    /**
     * 登录验证
     */
    @SuppressWarnings("unused")
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
       /* String username = String.valueOf(token.getPrincipal());
        String password = new String((char[]) token.getCredentials());
        System.out.println("aaaaaaa");
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, password, getName());*/
//        int i = 1/0;
        
        //获取用户账号
        User user = new User() ;
        user.setUsername("aa");
        user.setPassword("bb");
        if (user != null){
            //将查询到的用户账号和密码存放到 authenticationInfo用于后面的权限判断。第三个参数传入realName。
            AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),"a") ;
            return authenticationInfo ;
        }else{
            return  null ;
        }
    }

}

PermissionSign常量类:

package com.test.www.web.security;

/**
 * 权限标识配置类, <br>
 * 与 permission 权限表 中的 permission_sign 字段 相对应 <br>
 * 使用:
 * 
 * <pre>
 * &#064;RequiresPermissions(value = PermissionConfig.USER_CREATE)
 * public String create() {
 *     return &quot;拥有user:create权限,能访问&quot;;
 * }
 * </pre>
 * 
 **/
public class PermissionSign {
    //课程类别表权限
    public static final String PUB_COURSECATEGORY = "pub:coursecategory";

}

TestController类:

package com.test.www.web.controller;

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.test.www.test.exception.TestException;
import com.test.www.util.PrimaryKeyGenerator;
import com.test.www.web.entity.user.User;
import com.test.www.web.security.PermissionSign;
import com.test.www.web.service.user.UserService;

@RequestMapping("/test111")
@Controller
public class TestController {
    private final static Logger logger = LoggerFactory.getLogger(TestException.class);
    @Resource
    private UserService userService;
    
    /**
     * 注意:
     * 1.如果不是ajax提交表单,权限认证异常跳转到web.xml中配置的路径;
     * 2.如果是ajax请求,权限认证异常不是按照web.xml跳转
     */
    @RequestMapping("/add")
    @ResponseBody
    @RequiresPermissions(value=PermissionSign.PUB_COURSECATEGORY) //PUB_TRAININGTYPE PUB_COURSECATEGORY 增加权限控制
    public Map<String,Object> saveUser(
            User user,
            ModelMap map, HttpServletResponse response,
            HttpServletRequest request
            ){
        Map<String,Object> resultMap = new HashMap<String,Object>();
        try{
            
            user.setId(PrimaryKeyGenerator.getLongKey());
            int resultCount = userService.insertUser(user);
            
            if(resultCount>0){
                resultMap.put("msg", "success");
                resultMap.put("user", user);
            }

        }catch(Exception e){
            e.printStackTrace();
            resultMap.put("msg", "failure"); 
        }
        return resultMap;
    }
    
    @RequestMapping("/loginAdmin")
    public String login(){
        User user = new User();
        user.setUsername("aa");
        user.setPassword("bb");
        Subject subject = SecurityUtils.getSubject() ;
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword()) ;
        logger.info("登录成功1");
        logger.info("--info--");
        logger.debug("--debug--");
        logger.error("-error-");
        logger.warn("--warn--");
        System.out.println(System.getProperty("test2.root"));
        System.out.println(System.getProperty("Academic.root"));
        try {
            subject.login(token);
            return "index2" ;
        }catch (Exception e){
            //这里将异常打印关闭是因为如果登录失败的话会自动抛异常
//            e.printStackTrace();
            
            return "index" ;
        }
    }


}

说明:

1.登录验证:

   login()方法进行登录验证,subject.login(token);是验证核心,执行到这一步会进入SecurityRealm执行doGetAuthenticationInfo进行登录验证。

2.采用注解控制权限:

   执行saveUser方法操作,由于方法上面添加了权限注解@RequiresPermissions(value=PermissionSign.PUB_COURSECATEGORY),

   执行该操作会先进入到SecurityRealm的doGetAuthorizationInfo方法中获取用户的角色、权限并进行权限检查,只有拥有该权限的用户才能执行该操作,没有该权限则会转向未授权页面。

   去掉该注解,则不进行权限检查,不执行SecurityRealm的doGetAuthorizationInfo方法,所有用户都能执行该操作。

操作结果如图所示:

1.用户名密码都正确,用户拥有权限pub:coursecategory:

2.用户名密码正确,用户没有操作权限:

将doGetAuthorizationInfo中的permissions.add("pub:coursecategory");改为permissions.add("pub:coursecategory1");

操作结果如图所示:

其他情况可自行测试。

 

以上是关于shiro框架的使用的主要内容,如果未能解决你的问题,请参考以下文章

shiro权限安全验证框架

使用shiro框架,注销问题的解决

Shiro 安全框架详解一(概念+登录案例实现)

Apache shiro权限基本使用

Shiro 安全框架详解二(概念+权限案例实现)

Shiro安全框架——快速入门登录拦截用户认证请求授权