springmvc+mybatis整合shiro权限

硅谷探秘者 1507 0 0

springmvc+mybatis整合shiro权限


1.需要的jar包

  <properties>
    <shiro.version>1.3.2</shiro.version>
  </properties>

<dependency>
		    <groupId>org.apache.shiro</groupId>
		    <artifactId>shiro-core</artifactId>
		    <version>${shiro.version}</version>
	    </dependency>
	    <dependency>
		    <groupId>org.apache.shiro</groupId>
		    <artifactId>shiro-spring</artifactId>
		    <version>${shiro.version}</version>
	    </dependency>
	    <dependency>
		    <groupId>org.apache.shiro</groupId>
		    <artifactId>shiro-web</artifactId>
		    <version>${shiro.version}</version>
		</dependency> 
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-ehcache</artifactId>
			<version>${shiro.version}</version>
		</dependency>


2.web.xml配置

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml,classpath:applicationContext-shiro.xml</param-value>
    </context-param>
    
    
    <!-- shiro权限配置 -->
    <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>


3.applicationContext-shiro.xml配置

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">
	<description>shiro配置</description>
	
	<!-- 配置缓存管理器 -->
	<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml"/>
    </bean>

	<bean id="ShiroRealm" class="com.dzqc.model.common.shiro.ShiroRealm">
	</bean>
	
	<bean id="defaultWebSecurityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
		<property name="cacheManager" ref="cacheManager"/>
		<property name="realm" ref="ShiroRealm"></property>
	</bean>
	
	<bean id="shiroFilter" class="com.dzqc.model.common.shiro.ShiroPermissionFactory">
		<property name="securityManager" ref="defaultWebSecurityManager"></property>
		<property name="loginUrl" value="/ready/tologin"></property>
		<property name="successUrl" value="/ready/success"></property>
		<property name="unauthorizedUrl" value="/ready/error"></property>
		
		<property name="filters">
			<map>
				<entry key="roles">
	                    <bean class="com.dzqc.model.common.shiro.CustomRolesAuthorizationFilter" />  
	            </entry>
			</map>
		</property>
		
		<property name="filterChainDefinitions">
			<value>
				/static/**=anon
				/resources/** = anon
				/index.jsp=anon
				/ready/index=authc
				/ready/tologin=anon
				/login/login=anon
				/login/relogin=anon
				/login/getMenu=authc
			</value>
		</property>
	</bean>
	
</beans>


4.shiro缓存配置

<?xml version="1.0" encoding="UTF-8" ?>
<ehcache>
    <diskStore path="java.io.tmpdir/shiro-spring-sample"/>
    <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="false"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"/>
    <cache name="shiro-activeSessionCache"
           maxElementsInMemory="10000"
           eternal="true"
           overflowToDisk="true"
           diskPersistent="true"
           diskExpiryThreadIntervalSeconds="600"/>
    <cache name="org.apache.shiro.realm.SimpleAccountRealm.authorization"
           maxElementsInMemory="100"
           eternal="false"
           timeToLiveSeconds="600"
           overflowToDisk="false"/>
</ehcache>


5.请求的拦截和过滤

        所有的请求会经过isAccessAllowed()方法进行验证,如验证通过则返回true,如没有权限返回false

package com.dzqc.model.common.shiro;
import java.io.IOException;

import javax.servlet.ServletRequest;  
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import org.apache.shiro.web.util.WebUtils;

import com.alibaba.fastjson.JSONObject;
import com.dzqc.model.common.entity.ResultData;

/**
 * 
 * @author JIAJIAJIA
 * @data 2018年8月31日 下午2:56:12
 * @description TODO
 */
public class CustomRolesAuthorizationFilter extends AuthorizationFilter {  
    /***
     * 请求过滤的回调方法
     */
	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
		Subject subject = getSubject(request, response);
        if (subject.getPrincipal() == null) {
        	if (isAjaxRequest((HttpServletRequest)request)) {
        		response.setCharacterEncoding("UTF-8");
            	response.setContentType("application/json");
                ResultData resultData = new ResultData();
                resultData.setResult(1);
                resultData.setCode(401);
                resultData.setMessage("登录认证失效,请重新登录!");
                response.getWriter().write(JSONObject.toJSONString(resultData));
			}else {
				saveRequestAndRedirectToLogin(request, response);
			}
        } else {
            String unauthorizedUrl = getUnauthorizedUrl();
            if(isAjaxRequest((HttpServletRequest)request)) {
            	response.setCharacterEncoding("UTF-8");
            	response.setContentType("application/json");
                ResultData resultData = new ResultData();
                resultData.setResult(2);
                resultData.setCode(402);
                resultData.setMessage("您没有权限执行该操作!");
                response.getWriter().write(JSONObject.toJSONString(resultData));
            }else {
	            if (StringUtils.hasText(unauthorizedUrl)) {
	            	WebUtils.issueRedirect(request, response, unauthorizedUrl);
	            } else {
	                WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
	            }
            }
        }
        return false;
	}
	/**
	 * 请求过滤
	 */
    @Override  
    protected boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object mappedValue) throws Exception {  
        Subject subject = getSubject(req, resp);  
        String[] rolesArray = (String[]) mappedValue;  
  
        if (rolesArray == null || rolesArray.length == 0) { //没有角色限制,有权限访问  
            return true;  
        }  
        for (int i = 0; i < rolesArray.length; i++) {  
            if (subject.hasRole(rolesArray[i])) { //若当前用户是rolesArray中的任何一个,则有权限访问  
                return true;  
            }  
        }  
        return false;
    }  
    
    public static boolean isAjaxRequest(HttpServletRequest request) {
        String requestedWith = request.getHeader("x-requested-with");
        if (requestedWith != null && requestedWith.equalsIgnoreCase("XMLHttpRequest")) {
            return true;
        } else {
            return false;
        }
    }
}


6.从数据库中加载权限

        项目启动的时候会把所有的权限加载进shiro,访问的时候 进行对比有没有访问权限

package com.dzqc.model.common.shiro;
import java.util.LinkedHashMap;
import java.util.List;

import org.apache.shiro.config.Ini;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.config.IniFilterChainResolverFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.dzqc.model.common.entity.Function;
import com.dzqc.model.common.entity.Role;
import com.dzqc.model.common.service.SysAdminService;

/***
 * 
 * @author JIAJIAJIA
 * @data 2018年8月29日 上午11:22:58
 * @description TODO
 */

public class ShiroPermissionFactory extends ShiroFilterFactoryBean {
    public static String definition = "";

    @Autowired
	private SysAdminService sysAdminService;
    
    @Override
    public void setFilterChainDefinitions(String definitions) {
        definition = definitions;//记录配置的静态过滤链
        
        LinkedHashMap<String, String> m=new LinkedHashMap<String,String>();
		m.put("/index.jsp","anon");
		m.put("/trans/tologin","anon");
		m.put("/login","anon");
		m.put("/resources/**","anon");
		m.put("/relogin","anon");
		List<Role> role=sysAdminService.getFilterChain();
		
		for(Role r:role) {
			for(Function f:r.getFunctionList()) {
				if(m.containsKey(f.getLinkUrl())) {
					String u=m.get(f.getLinkUrl());
					u=u.substring(0,u.length()-1);
					u+=","+r.getName()+"]";
					m.put(f.getLinkUrl(),u);
				}else {
					m.put(f.getLinkUrl(),"roles["+r.getName()+"]");
				}
			}
		}
		m.put("/**","authc");
        
        //加载配置默认的过滤链
        Ini ini = new Ini();
        ini.load(definitions);
        Ini.Section section = ini.getSection(IniFilterChainResolverFactory.URLS);
        if (CollectionUtils.isEmpty(section)) {
            section = ini.getSection(Ini.DEFAULT_SECTION_NAME);
        }
        //加上数据库中过滤链
        section.putAll(m);
        setFilterChainDefinitionMap(section);
    }
}


7.自定义登录验证

        自定义验证规则,从数据库中查询,验证通过以后回调AuthorizationInfo()方法,将该用户所有的权限加入shiro,加入缓存,如果没有缓存,则每一次请求都会经过AuthorizationInfo()方法进行权限的查询和设置。

package com.dzqc.model.common.shiro;
import java.util.ArrayList;
import java.util.List;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
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.beans.factory.annotation.Autowired;

import com.dzqc.model.common.entity.Admin;
import com.dzqc.model.common.entity.Function;
import com.dzqc.model.common.entity.Role;
import com.dzqc.model.common.service.LoginService;

/***
 * @author JIAJIAJIA
 * @data 2018年8月23日 上午11:26:01
 * @description TODO
 * 自定义登陆 realm 验证
 */
public class ShiroRealm extends AuthorizingRealm{

	@Autowired
	private LoginService loginService;
	
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		// TODO Auto-generated method stub
		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
		if(token==null) {
			return null;
		}
		Admin admin = null;
		try {
			admin = loginService.selectByUsername(upToken.getUsername());
		} catch (Exception e) {
			e.printStackTrace();
		}
		if(admin==null){
			throw new UnknownAccountException("用户不存在!");
		}else {
			if(!admin.getPassword().equals(new String(upToken.getPassword()))){
				System.out.println(admin.getPassword()+":"+new String(upToken.getPassword()));
				throw new LockedAccountException("密码错误");
			}
		}
		List<Role> role=loginService.selectRoleAndFunction(admin.getId());
		admin.setRoleList(role);
		SimpleAuthenticationInfo info = null; //new SimpleAuthenticationInfo(principal, credentials, realmName);
		info = new SimpleAuthenticationInfo(admin,admin.getPassword(),getName());
		return info;
	}

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
		Admin a=(Admin) principal.getPrimaryPrincipal();
		SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        List<String> permissions=new ArrayList<String>();
        List<String> roles=new ArrayList<String>();
        for(Role r:a.getRoleList()) {
        	roles.add(r.getName());
        	for(Function f:r.getFunctionList()){
        		permissions.add(f.getLinkUrl());
        	}
        }
        info.addRoles(roles);//设置角色
        info.addStringPermissions(permissions);//设置权限
        return info;
	}
}




评论区
请写下您的评论...
暂无评论...
猜你喜欢
框架 1452 1.pom文件dependencygroupIdorg.apache.shiro/groupIdartifactIdshiro-spring/artifactIdversion1.4.0/version/dependencydependency groupIdorg.apache.shiro/groupId artifactIdshiro-ehcache/artifactId vers
框架 2521 springbootmybatis1.创建maven项目2.sql文件SETNAMESutf8mb4;SETFOREIGN_KEY_CHECKS=0
数据库 851 用户管理创建用户删除用户设置密码管理授撤销授刷新一、用户管理1.创建用户语法:createuser[用户名]identifiedby'[密码
框架 2304 在springboot视图层,官方推荐使用thymeleaf。thymeleaf只是渲染html的一种方式,是一种模板。第一步创建一个maven项目第二步:修改Jdk版本,添加thymeleaf
框架 2634 1.配置springboot支持websocketpackagecom.example.demo.websocket;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.so
weblog 984 pomparent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.1.3.RELEASE/version /parentdependencies dependency groupIdorg.springframework.boot/group
框架 2578 1.项目结构2.pom文件依赖?xmlversion="1.0"encoding="UTF-8"?projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.
框架 2379 安装redis数据库参考:http://www.jiajiajia.club/blog/artical/166redis配置详解参考:http://www.jiajiajia.club/blog/artical/210安装完数据库以后如果不是本地连接记得修改密码requirepass。默认是没有密码需要后台运行修改daemonizeyes默认是noyml配置文件spring:redis:host:
归档
2018-11  12 2018-12  33 2019-01  28 2019-02  28 2019-03  32 2019-04  27 2019-05  33 2019-06  6 2019-07  12 2019-08  12 2019-09  21 2019-10  8 2019-11  15 2019-12  25 2020-01  9 2020-02  5 2020-03  16 2020-04  4 2020-06  1 2020-07  7 2020-08  13 2020-09  9 2020-10  5 2020-12  3 2021-01  1 2021-02  5 2021-03  7 2021-04  4 2021-05  4 2021-06  1 2021-07  7 2021-08  2 2021-09  8 2021-10  9 2021-11  16 2021-12  14 2022-01  7 2022-05  1 2022-08  3 2022-09  2 2022-10  2 2022-12  5 2023-01  3 2023-02  1 2023-03  4 2023-04  2 2023-06  3 2023-07  4 2023-08  1 2023-10  1 2024-02  1 2024-03  1
标签
算法基础 linux 前端 c++ 数据结构 框架 数据库 计算机基础 储备知识 java基础 ASM 其他 深入理解java虚拟机 nginx git 消息中间件 搜索 maven redis docker dubbo vue 导入导出 软件使用 idea插件 协议 无聊的知识 jenkins springboot mqtt协议 keepalived minio mysql ensp 网络基础 xxl-job rabbitmq haproxy srs 音视频 webrtc javascript
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。