springboot 集成shiro
首先看下shiro configuration 的配置,重要部分用红色标出了
package cn.xiaojf.today.shiro.configuration; import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import cn.xiaojf.today.sys.security.credentials.RetryLimitHashedCredentialsMatcher;
import cn.xiaojf.today.sys.security.filter.MyLogoutFilter;
import cn.xiaojf.today.sys.security.filter.RoleAuthorizationFilter;
import cn.xiaojf.today.sys.security.realm.UsernameRealm;
import cn.xiaojf.today.sys.service.SysResService;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.DelegatingFilterProxy; import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map; /**
* shiro配置
* @author xiaojf 2017/2/10 11:30.
*/
@Configuration
public class ShiroConfiguration {
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new DelegatingFilterProxy("shiroFilter"));
filterRegistrationBean.addInitParameter("targetFilterLifecycle", "true");
filterRegistrationBean.setEnabled(true);
filterRegistrationBean.addUrlPatterns("/*");
return filterRegistrationBean;
} @Bean
public RetryLimitHashedCredentialsMatcher credentialsMatcher() {
RetryLimitHashedCredentialsMatcher credentialsMatcher = new RetryLimitHashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("sha");
credentialsMatcher.setHashIterations(2);
credentialsMatcher.setStoredCredentialsHexEncoded(true);
credentialsMatcher.setRetryCount(5);
credentialsMatcher.setRetryTime(1800000);
return credentialsMatcher;
} @Bean
public UsernameRealm usernameRealm(RetryLimitHashedCredentialsMatcher credentialsMatcher) {
UsernameRealm usernameRealm = new UsernameRealm();
usernameRealm.setCredentialsMatcher(credentialsMatcher);
usernameRealm.setCachingEnabled(true);
return usernameRealm;
} @Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
} @Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
daap.setProxyTargetClass(true);
return daap;
} @Bean
public DefaultWebSecurityManager securityManager(UsernameRealm usernameRealm) {
DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
dwsm.setRealm(usernameRealm);
return dwsm;
} @Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager) {
AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
aasa.setSecurityManager(defaultWebSecurityManager);
return aasa;
} @Bean
public MyLogoutFilter logoutFilter() {
MyLogoutFilter myLogoutFilter = new MyLogoutFilter();
myLogoutFilter.setRedirectUrl("/login/index");
return myLogoutFilter;
} @Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager,
MyLogoutFilter logoutFilter, ApplicationContext context) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
shiroFilterFactoryBean.setLoginUrl("/login/index");
shiroFilterFactoryBean.setUnauthorizedUrl("/login/index"); Map<String, Filter> filters = new LinkedHashMap<>();
// filters.put("logout", logoutFilter);
filters.put("role", new RoleAuthorizationFilter()); shiroFilterFactoryBean.getFilters().putAll(filters);//加载自定义拦截器 SysResService resService = context.getBean(SysResService.class);//只有通过这种方式才能获得resService,因为此处会优先于resService实例化
loadShiroFilterChain(shiroFilterFactoryBean,resService);//加载拦截规则
return shiroFilterFactoryBean;
} private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean,SysResService resService) {
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
//默认拦截规则
filterChainDefinitionMap.put("/login/index", "anon");
filterChainDefinitionMap.put("/error/403", "anon");
filterChainDefinitionMap.put("/error/404", "anon");
filterChainDefinitionMap.put("/error/500", "anon");
filterChainDefinitionMap.put("/login/auth", "anon");
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/plugins/**", "anon");
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/images/**", "anon");
//用户自定义拦截规则
filterChainDefinitionMap = resService.loadFilterChainDefinitions(filterChainDefinitionMap);
//都不满足的时候,需要超级管理员权限才能访问
filterChainDefinitionMap.put("/**", "role[ROLE_SUPER]");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
} @Bean
public ShiroDialect shiroDialect() {//thymeleaf 集成shiro使用,如果没有可以删除
return new ShiroDialect();
}
}
自定义realm,用于认证和授权
package cn.xiaojf.today.sys.security.realm; import cn.xiaojf.today.base.constant.DataStatus;
import cn.xiaojf.today.base.constant.SystemConstant;
import cn.xiaojf.today.sys.entity.SysUser;
import cn.xiaojf.today.sys.service.SysUserService;
import org.apache.shiro.authc.*;
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.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy; import java.util.Set; /**
* 根据用户名和密码校验登陆
*
* @author xiaojf 2016-01-07 16:05:55
*/
public class UsernameRealm extends AuthorizingRealm { /**
* 系统用户service
*/
@Autowired
@Lazy
private SysUserService sysUserService; /**
* 加载用户授权信息, 包括权限资源和角色\用户组资源
*
* @author xiaojf 2016-01-07 16:05:55
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 登陆名
String username = (String) principals.getPrimaryPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); Set<String> roles = sysUserService.loadEnabledRolesByUsername(username); if (roles.contains(SystemConstant.ROLE_SUPER)) {
authorizationInfo.addStringPermission("*");
}else {
// 加载权限资源
authorizationInfo.setStringPermissions(sysUserService.loadEnabledPermissionsByUsername(username));
} // 加载角色/用户组
authorizationInfo.setRoles(roles); return authorizationInfo;
} /**
* 加载用户身份认证信息
*
* @author xiaojf 2016-01-07 16:05:55
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal(); // 获取账号信息
SysUser sysUser = sysUserService.getByUsername(username); if (sysUser == null) {
throw new UnknownAccountException(); // 没找到帐号
} if (sysUser.getStatus() == DataStatus.LOGIC_DELETE.getValue()) {
throw new UnknownAccountException(); // 没找到帐号
} if (sysUser.getStatus() == DataStatus.DISABLE.getValue()) {
throw new LockedAccountException(); // 帐号锁定
} SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(sysUser.getUsername(),
sysUser.getPwd(), ByteSource.Util.bytes(sysUser.getSalt()),
getName()); return authenticationInfo;
} }
自定义登出过滤器
package cn.xiaojf.today.sys.security.filter; import org.apache.shiro.web.filter.authc.LogoutFilter; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.util.Date; /**
* 自定义退出过滤器
* @author xiaojf 294825811@qq.com
*
* 2015-3-20
*/
public class MyLogoutFilter extends LogoutFilter { @Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
return true;
}
}
自定义权限校验过滤器
package cn.xiaojf.today.sys.security.filter; import com.alibaba.fastjson.JSON;
import cn.xiaojf.today.base.model.CommonResult;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import org.apache.shiro.web.util.WebUtils; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Set; /**
* 自定义认证器,区分ajax请求
* @author xiaojf 2017/2/10 11:30.
*/
public class RoleAuthorizationFilter extends AuthorizationFilter { public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
throws IOException { Subject subject = getSubject(request, response);
String[] rolesArray = (String[]) mappedValue; if (rolesArray == null || rolesArray.length == 0) {
// no roles specified, so nothing to check - allow access.
return true;
} Set<String> roles = CollectionUtils.asSet(rolesArray);
for (String role : roles) {
if (subject.hasRole(role)) {
return true;
}
}
return false;
} @Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response; Subject subject = getSubject(request, response); if (subject.getPrincipal() == null) {
if ("XMLHttpRequest".equalsIgnoreCase(httpServletRequest.getHeader("X-Requested-With"))) {
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setHeader("Charset","UTF-8");
PrintWriter out = httpServletResponse.getWriter(); CommonResult result = new CommonResult(false);
result.setCode("401");
result.setMsg("请重新登录"); out.write(JSON.toJSONString(result));
out.flush();
out.close();
} else {
// saveRequestAndRedirectToLogin(request, response);
String unauthorizedUrl = getUnauthorizedUrl();
WebUtils.issueRedirect(request, response, unauthorizedUrl);
}
} else {
if ("XMLHttpRequest".equalsIgnoreCase(httpServletRequest.getHeader("X-Requested-With"))) {
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setHeader("Charset","UTF-8");
PrintWriter out = httpServletResponse.getWriter(); CommonResult result = new CommonResult(false);
result.setCode("403");
result.setMsg("没有足够的权限: "+((HttpServletRequest) request).getServletPath()); out.println(JSON.toJSONString(result));
out.flush();
out.close();
} else {
String unauthorizedUrl = getUnauthorizedUrl();
if (StringUtils.hasText(unauthorizedUrl)) {
WebUtils.issueRedirect(request, response, unauthorizedUrl);
} else {
WebUtils.toHttp(response).sendError(403);
}
}
}
return false;
}
}
springboot 集成shiro的更多相关文章
- SpringBoot集成Shiro并用MongoDB做Session存储
之前项目鉴权一直使用的Shiro,那是在Spring MVC里面使用的比较多,而且都是用XML来配置,用Shiro来做权限控制相对比较简单而且成熟,而且我一直都把Shiro的session放在mong ...
- springboot集成shiro实现权限认证
github:https://github.com/peterowang/shiro 基于上一篇:springboot集成shiro实现身份认证 1.加入UserController package ...
- SpringBoot集成Shiro 实现动态加载权限
一.前言 本文小编将基于 SpringBoot 集成 Shiro 实现动态uri权限,由前端vue在页面配置uri,Java后端动态刷新权限,不用重启项目,以及在页面分配给用户 角色 . 按钮 .ur ...
- SpringBoot学习笔记(五):SpringBoot集成lombok工具、SpringBoot集成Shiro安全框架
SpringBoot集成lombok工具 什么是lombok? 自动生成setget方法,构造函数,打印日志 官网:http://projectlombok.org/features/index. 平 ...
- SpringBoot集成Shiro安全框架
跟着我的步骤:先运行起来再说 Spring集成Shiro的GitHub:https://github.com/yueshutong/shiro-imooc 一:导包 <!-- Shiro安全框架 ...
- springboot集成shiro 实现权限控制(转)
shiro apache shiro 是一个轻量级的身份验证与授权框架,与spring security 相比较,简单易用,灵活性高,springboot本身是提供了对security的支持,毕竟是自 ...
- 【Shiro】SpringBoot集成Shiro
项目版本: springboot2.x shiro:1.3.2 Maven配置: <dependency> <groupId>org.apache.shiro</grou ...
- SpringBoot集成Shiro实现权限控制
Shiro简介 Apache Shiro是一个功能强大且易于使用的Java安全框架,用于执行身份验证,授权,加密和会话管理.使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序-从最小的移 ...
- springboot集成shiro——使用RequiresPermissions注解无效
在Springboot环境中继承Shiro时,使用注解@RequiresPermissions时无效 @RequestMapping("add") @RequiresPermiss ...
随机推荐
- 1094:零起点学算法01——第一个程序Hello World!
Description 题目很简单 输出"Hello World!"(不含引号),并换行. Input 没有输入 Output 输出"Hello World!" ...
- python paramiko模块简介
一:简介 paramiko是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. 由于使用的是python这样的能够跨平台运行的语言,所以所有python支 ...
- C++ fstream 详解
最近在写哈夫曼压缩,遇到了一个比较让人头疼的问题,那就是对文件的读写操作,尤其是以二进制的形式来读写,无奈C++Primer第五版上写的并不详细,很多让人困惑的地方没有涉及或者没有讲清楚.于是这几天我 ...
- jquery 中 eq()遍历方法 和:eq()选择器的区别
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- 学习Sass之安装篇
Sass是基于ruby开发的,所以想要用Sass要先搭建ruby环境 1 Mac下安装 2 windows下安装 3 下载koala,只需要下载这个软件,其余什么都不需要你安装
- 学习vue 20天,我写了点东西
往昔 最初团队里使用Angularjs进行开发,刚开始还好,到了项目后期越发感觉Angularjs太重了,以至于后来重构项目时,毅然放弃Angularjs,投入了Vue的怀抱.除了组建团队时,是我搭建 ...
- Laravel框架一:原理机制篇
Laravel作为在国内国外都颇为流行的PHP框架,风格优雅,其拥有自己的一些特点.以下是本人一点粗浅的认识,不敢奢求他人同意,更不能一一而足,仅为自己做一点总结而已. 一. 请求周期 Laravel ...
- angularjs中常用的ng指令介绍【转载】
原文:http://www.cnblogs.com/lvdabao/p/3379659.html 一.模板中可使用的东西及表达式 模板中可以使用的东西包括以下四种: 指令(directive).ng提 ...
- OK 开始实践书上的项目一:即使标记
OK 开始实践书上的项目一:及时标记 然而....又得往前面看啦! ----------------------我是分割线------------------------ 代码改变世界
- iOS开发 - CocoaPods安装和使用教程
一.CocoaPods简介 1.什么是CocoaPods CocoaPods是iOS的包管理工具. 2.为什么要使用CocoaPods 在开发iOS项目时,经常会使用第三方开源库,手动引入流程复杂,并 ...