基于spring框架的apache shiro简单集成
关于项目的安全保护,我一直想找一个简单配置就能达到目的的方法,自从接触了shiro,这个目标总算达成了,以下结合我使用shiro的经验,谈谈比较轻便地集成该功能。
首先我们先了解一下shiro是什么。
apache shiro 是一个功能强大和易于使用的Java安全框架,为开发人员提供一个直观而全面的的解决方案的认证,授权,加密,会话管理。
其实按照我个人的理解,就是个过滤器,按照配置(或者注解)的规则进行权限验证。
我的项目基于maven管理依赖jar包,首先把apache shiro相关需要用到的jar引入:
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.1</version>
</dependency> <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.1</version>
</dependency>
其中shiro-web和shiro-spring必须,如果要缓存权限的话,就引入shiro-ehcache,后边会详细说道shiro-ehcache的使用。
看一下login.action里是如何实现用户登录写入的,获取用户表单信息以及查询数据库验证就不说了,直接上关键代码:
//验证用户信息后进行token写入,这里为了简单,我把用户的id和姓名作为token的username和password
UsernamePasswordToken token = new UsernamePasswordToken(m.getId()
.toString(), m.getUsername());
Subject subject1 = SecurityUtils.getSubject();
subject1.login(token);
subject1.getSession();
既然是个过滤器,那我们就看一下这个过滤器的写法:
package com.airfey.tech.nuo.action.shiro.filter; import java.io.IOException;
import java.security.Principal; import javax.annotation.Resource;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
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.subject.Subject; import com.airfey.tech.nuo.common.security.MD5;
import com.airfey.tech.nuo.core.domain.Manager;
import com.airfey.tech.nuo.core.service.ManagerService; public class shiroFilter implements Filter {
//管理员用户service
@Resource
private ManagerService managerService; @Override
public void init(FilterConfig filterConfig) throws ServletException { } @Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException { Subject subjects = SecurityUtils.getSubject(); HttpServletRequest requestHttp = (HttpServletRequest) request;
HttpServletResponse responseHttp = (HttpServletResponse) response; Principal principal = requestHttp.getUserPrincipal();
if (null != principal) {
//principal.getName()里保存的是用户的id,就是上边登录处token里的信息
System.out.println(principal.getName());
Manager m = managerService.findOne(Long.parseLong(principal
.getName()));
if (null != m && 1 == m.getAudit()) {
UsernamePasswordToken token = new UsernamePasswordToken(
m.getId(), m.getId());//作为例子,这里我只是把用户id放进了token,你可以修改成其它复杂点的信息
Subject subject1 = SecurityUtils.getSubject();
subject1.login(token);
subject1.getSession();
} else {
if (subjects != null) {
subjects.logout();
}
}
} chain.doFilter(requestHttp, responseHttp); } @Override
public void destroy() { } }
至此,可以说登录和过滤器已经完成了。然后就进行web.xml和spring文件以及权限验证的实现。
1、在web.xml里加入shiro的过滤器配置:
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
此过滤器要位于所有过滤器的前面。
2、权限验证代码实现,我们写一个realm类集成shiro的AuthorizingRealm
package com.airfey.tech.nuo.action.shiro.realm; import javax.annotation.Resource; 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.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection; public class ShiroRealm extends AuthorizingRealm { @Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
if (principals == null) {
throw new AuthorizationException(
"PrincipalCollection method argument cannot be null.");
}
String username = (String) getAvailablePrincipal(principals);
System.out.println("-------------------" + username);//输出的其实是用户id SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 增加默认角色
info.addRole("ROLE_USER");
/*以下可以从数据库获取用户的角色以及权限信息,获取到的信息添加入info即可,具体获取数据库的代码我就省略了*/
// // 增加自定义角色
// if (null != userInfo.getRoleList()) {
// for (RoleInfo roleInfo : userInfo.getRoleList()) {
// if (null != roleInfo.getName()
// && !"".equals(roleInfo.getName())) {
// info.addRole(roleInfo.getName());
// }
// }
// }
// if (null != userInfo.getModuleInfo()) {
// for (ModuleInfo moduleInfo : userInfo.getModuleInfo()) {
// if (null != moduleInfo.getGuid()
// && !"".equals(moduleInfo.getGuid())) {
// info.addStringPermission(moduleInfo.getGuid());
// }
// }
// } return info; } @Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken authcToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
String userName = token.getUsername();
if (userName != null && !"".equals(userName)) { return new SimpleAuthenticationInfo(token.getPrincipal(),
token.getPassword(), token.getUsername());
}
return null;
} /**
* 清空用户关联权限认证,待下次使用时重新加载。
*
* @param principal
*/
public void clearCachedAuthorizationInfo(String principal) {
SimplePrincipalCollection principals = new SimplePrincipalCollection(
principal, getName());
clearCachedAuthorizationInfo(principals);
} /**
* 清空所有关联认证
*/
public void clearAllCachedAuthorizationInfo() {
Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
if (cache != null) {
for (Object key : cache.keys()) {
cache.remove(key);
}
}
}
}
3、applicationContext.xml的配置 (这里只保留了shiro相关的信息)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd"> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="successUrl" value="/manage/index.do" />
<property name="loginUrl" value="/manage/login.do" />
<property name="unauthorizedUrl" value="/manage/401.html" />
<property name="filters">
<map>
<entry key="authc" value-ref="shiro"></entry>
</map>
</property>
<property name="filterChainDefinitions">
<value>
/manage/admin.html = authc,perms[shiro_admin:view]
/manage/user.html=authc,perms[shiro_user:view]
/manage/login.do=anon
/manage/401.html=anon
/manage/js/**=anon
/manage/img/**=anon
/manage/kindeditor/**=anon
/manage/**=authc,roles["ROLE_USER"]
/**=anon
</value>
</property>
</bean>
<bean id="shiro" class="com.airfey.tech.nuo.action.shiro.filter.shiroFilter"> </bean>
<bean id="shiroRealm" class="com.airfey.tech.nuo.action.shiro.realm.ShiroRealm" />
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="shiroRealm" />
<property name="cacheManager" ref="shiroEhcacheManager" />
</bean> <!-- 用户授权信息Cache, 采用EhCache,需要的话就配置上此信息 -->
<bean id="shiroEhcacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache-shiro.xml" />
</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>
验证规则里如下让静态文件比如js img 目录配置上anon
/manage/admin.html = authc,perms[shiro_admin:view]
/manage/user.html=authc,perms[shiro_user:view]
/manage/login.do=anon
/manage/401.html=anon
/manage/js/**=anon
/manage/img/**=anon
/manage/kindeditor/**=anon
/manage/**=authc,roles["ROLE_USER"]
/**=anon
结束,收工。好久不写这么长的博文了,敲起来真费劲。原创文章,文中难免有遗漏或者错误之处,请指正。
基于spring框架的apache shiro简单集成的更多相关文章
- 基于Spring框架的简单多数据源切换解决办法
基于Spring框架的简单多数据源切换解决办法 Spring框架JDBC包提供了一个抽象类AbstractRoutingDataSource提供了动态切换数据库的基础方法.我们仅仅需要实现一个简单的数 ...
- 基于Spring框架应用的权限控制系统的研究和实现
摘 要: Spring框架是一个优秀的多层J2EE系统框架,Spring本身没有提供对系统的安全性支持.Acegi是基于Spring IOC 和 AOP机制实现的一个安全框架.本文探讨了Acegi安全 ...
- web应用安全框架选型:Spring Security与Apache Shiro
一. SpringSecurity 框架简介 官网:https://projects.spring.io/spring-security/ 源代码: https://github.com/spring ...
- 基于Spring Aop实现类似shiro的简单权限校验功能
在我们的web开发过程中,经常需要用到功能权限校验,验证用户是否有某个角色或者权限,目前有很多框架,如Shiro Shiro有基于自定义登录界面的版本,也有基于CAS登录的版本,目前我们的系统是基于C ...
- 基于Spring框架的Shiro配置
一.在web.xml中添加shiro过滤器 <!-- Shiro filter--> <filter> <filter-name>shiroFilter</ ...
- 第一次玩博客,今天被安利了一个很方便JDBC的基于Spring框架的一个叫SimpleInsert的类,现在就来简单介绍一下
首先先对这段代码的简单介绍,我之前在需要操作JDBC的时候总是会因为经常要重新写SQL语句感到很麻烦.所以就能拿则拿不能拿的就简单地封装了一下. 首先是Insert.Spring框架的JDBC包里面的 ...
- 基于Spring框架的Shiro配置(转发:http://kdboy.iteye.com/blog/1103794)
一.在web.xml中添加shiro过滤器 <!-- Shiro filter--> <filter> <filter-name>shiroFilter</f ...
- Java开源安全框架之Apache Shiro
APACHE SHIRO安全框架 1 背景 Shiro项目始于2003年初,当时它叫JSecurity项目,当时对于Java应用开发人员没有太多的安全替代方案,始终被一个叫JAAS(Java ...
- Spring框架-IOC和AOP简单总结
参考博客: https://blog.csdn.net/qq_22583741/article/details/79589910 1.Spring框架是什么,为什么,怎么用 1.1 Spring框架是 ...
随机推荐
- KMS服务器软件-windows/OpenWRT-X64版
软件项目: https://github.com/Wind4/vlmcsd windows版kms服务器 https://files.cnblogs.com/files/SilenceRet/vlmc ...
- ArcGIS Earth1.9最新版安装和使用教程
1.下载ArcGIS Earth 官网下载地址:https://www.esri.com/en-us/arcgis/products/arcgis-earth 在这个网页的最下面填上信息,就可以下载了 ...
- nginx 服务器在上传文件出现413代码的解决方法
打开nginx主配置文件nginx.conf 找到http{}段,添加client_max_body_size 20m;
- sed 指定行范围匹配(转)
sed -n '5,10{/pattern/p}' file sed是一个非交互性性文本编辑器,它编辑文件或标准输入 导出的文件拷贝.标准输入可能是来自键盘.文件重定向.字符串或变量,或者是一个管道文 ...
- flexible.js结合rem实现移动端自适应布局
1. 配置开发工具(sublime)插件 https://github.com/flashlizi/cssrem 注意: 只有在‘.css’后缀文件才能使用此插件功能 2. 在h ...
- Redis未授权漏洞利用方式
总结一下redis未授权拿shell: redis-cli -h ip >info 查看系统类型 Windows: 1.找网站绝对路径 2.config set dir 绝对路径根路径 conf ...
- Qt Creator无法debug,报错:The selected debugger may be inappropriate for the inferior. Examining symbols and setting breakpoints by file name and line number may fail. The inferior is in the Portable ...
看到这个报错我是绝望的 解决:下载windows sdk win10 sdk 只安装Debugging Tools for Windows 打开 工具-选项-Kits 安装sdk成功后我们可以看到 ...
- Python2.7-fractions
fractions 模块,提供分数格式存储数据,没多大用处,除了模块里的最大公约数函数 gcd(a,b) 模块类和方法: fractions.Fraction(numerator=0, denomin ...
- Python2.7-canlendar
calendar模块的主要功能是针对万年历.星期几的,此外模块内还有方便的判断闰年.获取月份名.星期名的方法 1.模块的类 1.1.calendar.Calendar([firstweekday]) ...
- day42
今日内容: 1.子查询补充 2.正则表达式 3.pymysql 1.子查询补充 什么是子查询? 将上一次查询的结果作为下一次查询的条件或原数据 又称为内查询 作用:当你的需求,一次查询无法满足的时候( ...