springmvc+mybatis整合shiro权限
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;
}
}
评论区
请写下您的评论...
猜你喜欢
blog
springboot整合shiro权限
框架
1452
1.pom文件dependencygroupIdorg.apache.shiro/groupIdartifactIdshiro-spring/artifactIdversion1.4.0/version/dependencydependency groupIdorg.apache.shiro/groupId artifactIdshiro-ehcache/artifactId vers
blog
springboot整合mybatis
框架
2521
springboot整合mybatis1.创建maven项目2.sql文件SETNAMESutf8mb4;SETFOREIGN_KEY_CHECKS=0
blog
mysql用户权限控制sql语法案例
数据库
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.
blog
springboot整合redis数据库
框架
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
目录
没有一个冬天不可逾越,没有一个春天不会来临。最慢的步伐不是跬步,而是徘徊,最快的脚步不是冲刺,而是坚持。