Apache Shiro 整合Spring 进行权限验证 以及在Freemarker中使用shiro标签
Apache Shiro是什么?
Apache Shiro是一个功能强大且易于使用的Java安全框架,进行认证,授权,加密和会话管理。随着Shiro的易于理解的API,你可以快速,轻松地确保任何应用程序 - 移动应用从最小的到最大的Web和企业应用。
如何使用Apache Shiro(这里指与Spring 集成)?
1. 首先去官方网站下载相关jar包(这里使用1.2.2版本),其中包括:
shiro-core-1.2.2.jar
shiro-spring-1.2.2.jar
shiro-web-1.2.2.jar
(还需要slf4j相关jar支持)
2.在web.xml中配置shiroFilter(注意这个filter一定要放在所有的filter之前,否则不能成功使用)
3.创建一个applicationContext-shiro.xml,对shiro进行配置,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- =========================================================
Shiro Components
========================================================= -->
<!-- Shiro's main business-tier object for web-enabled applications
(use org.apache.shiro.web.mgt.DefaultWebSecurityManager instead when there is no web environment)-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- Single realm app (realm configured next, below). If you have multiple realms, use the 'realms'
property instead. -->
<!--这里的sampleRealm需要我们自己实现,主要包括2个方法
1. 用户登录的验证(授权)
2. 用户具有的角色和权限(认证)
且看下面介绍-->
<property name="realm" ref="sampleRealm"/>
<!-- Uncomment this next property if you want heterogenous session access or clusterable/distributable
sessions. The default value is 'http' which uses the Servlet container's HttpSession as the underlying
Session implementation.
<property name="sessionMode" value="native"/> -->
</bean>
<!-- Post processor that automatically invokes init() and destroy() methods -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- 自定义角色过滤器 支持多个角色可以访问同一个资源 eg:/home.jsp = authc,roleOR[admin,user] 用户有admin或者user角色 就可以访问-->
<bean id="roleOR" class="com.yale.app.security.OneRoleAuthorizationFilter"/>
<!-- Define the Shiro Filter here (as a FactoryBean) instead of directly in web.xml -
web.xml uses the DelegatingFilterProxy to access this bean. This allows us
to wire things with more control as well utilize nice Spring things such as
PropertiesPlaceholderConfigurer and abstract beans or anything else we might need: -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/page/login.jsp"/>
<property name="successUrl" value="/page/index.jsp"/>
<property name="unauthorizedUrl" value="/register/unauthorized"/>
<!-- The 'filters' property is usually not necessary unless performing an override, which we
want to do here (make authc point to a PassthruAuthenticationFilter instead of the
default FormAuthenticationFilter: -->
<property name="filters">
<util:map>
<entry key="authc">
<bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter"/>
</entry>
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/page/login.jsp = anon
/page/register/* = anon
/page/index.jsp = authc
/page/addItem* = authc,roles[数据管理员]
/page/file* = authc,roleOR[数据管理员,普通用户]
/page/listItems* = authc,roleOR[数据管理员,普通用户]
/page/showItem* = authc,roleOR[数据管理员,普通用户]
/page/updateItem*=authc,roles[数据管理员]
</value>
</property>
</bean>
</beans>
其中的定义官网文档有详细的解释,这里不做描述!
然后在applicationContext.xml中引入该文件!
3. 实现sampleRealm,继承AuthorizingRealm,并重写认证授权方法
1) 我们首先创建两张表User,Role(这里只做最简单的基于用户-角色的权限验证,如果需要细粒度的控制,自己在添加权限表Permissions然后进行关联操作)
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`userid` int(10) NOT NULL AUTO_INCREMENT,
`loginName` varchar(16) DEFAULT NULL,
`password` varchar(16) DEFAULT NULL,
`mail` varchar(50) DEFAULT NULL,
`roleid` int(10) NOT NULL,
PRIMARY KEY (`userId`),
KEY `RoleId` (`roleid`),
CONSTRAINT `users_ibfk_1` FOREIGN KEY (`roleid`) REFERENCES `roles` (`RoleId`)
) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `roles`;
CREATE TABLE `roles` (
`roleid` int(10) NOT NULL,
`roleName` varchar(50) DEFAULT NULL,
PRIMARY KEY (`RoleId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--插入测试数据
INSERT INTO `roles` VALUES ('1', '普通用户');
INSERT INTO `roles` VALUES ('2', '数据管理员');
INSERT INTO `users` VALUES ('1', 'yale', '123456', 'yale@126.com', '1');
INSERT INTO `users` VALUES ('2', 'admin', 'admin', 'admin@126.com', '2');
然后,创建对应的实体类,Dao操作,Service。这里不做细述
接下来我们看sampleRealm具体内容:
import org.apache.shiro.SecurityUtils;
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.authc.credential.AllowAllCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.yale.app.service.UserOperator;
import com.yale.app.model.Role;
import com.yale.app.model.User;
/**
* The Spring/Hibernate sample application's one and only configured Apache Shiro Realm.
*
* <p>Because a Realm is really just a security-specific DAO, we could have just made Hibernate calls directly
* in the implementation and named it a 'HibernateRealm' or something similar.</p>
*
* <p>But we've decided to make the calls to the database using a UserDAO, since a DAO would be used in other areas
* of a 'real' application in addition to here. We felt it better to use that same DAO to show code re-use.</p>
*/
@Component
public class SampleRealm extends AuthorizingRealm {
@Autowired
private UserOperator userOperator;
public SampleRealm() {
setName("SampleRealm"); //This name must match the name in the User class's getPrincipals() method
// setCredentialsMatcher(new Sha256CredentialsMatcher());
setCredentialsMatcher(new AllowAllCredentialsMatcher());
}
//认证信息,主要针对用户登录,(下文讲述在action或者controller登录过程代码)
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
String password = String.valueOf(token.getPassword());
//调用操作数据库的方法查询user信息
User user = userOperator.login( token.getUsername());
if( user != null ) {
if(password.equals(user.getPassword())){
Session session= SecurityUtils.getSubject().getSession();
session.setAttribute("username", user.getLoginName());
return new SimpleAuthenticationInfo(user.getUserId(), user.getPassword(), getName());
}else{
return null;
}
} else {
return null;
}
}
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String userId = (String) principals.fromRealm(getName()).iterator().next();
User user = userOperator.getById(userId);
if( user != null ) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Role role = userOperator.getByRoleId(user.getRoleId());
info.addRole(role.getRoleName());
// info.addStringPermissions( role.getPermissions() );//如果你添加了对权限的表,打开此注释,添加角色具有的权限
return info;
} else {
return null;
}
}
}
--注意shiro配置文件中
<bean id="roleOR" class="com.yale.app.security.OneRoleAuthorizationFilter"/>
OneRoleAuthorizationFilter:为验证多个角色可以访问同一个资源的定义:
import java.io.IOException;
import java.util.Set;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
public class OneRoleAuthorizationFilter extends AuthorizationFilter{
@SuppressWarnings({"unchecked"})
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;
}
boolean flag = false;
Set<String> roles = CollectionUtils.asSet(rolesArray);
for (String string : roles) {
if(subject.hasRole(string)){
flag = true;
}
}
return flag;
}
}
4. 在工程WebRoot/page下,创建login.jsp,index.jsp,register.jsp;
这里主要说明index.jsp
Shiro具有自己的JSP / GSP Tag Library,用户做权限检查判断等等
所以我们在index.jsp引入shiro 标签库
里面用很多的标签,这里我们主要说明:
如果用户具有administrator 角色我们就给他显示这个链接
如果用户有user:create权限 我们显示此链接
根据我上文提到的user和role表中的数据,我们在index.jsp,做如下测试:
<shiro:hasRole name="数据管理员”>
您好管理员同志!
</shiro:hasRole>
<shiro:hasRole name="普通用户”>
您好普通用户!
</shiro:hasRole>
5. jsp页面写完后,接下来我们看UserAction(用户登录,退出等操作):
//登录
public String login(){
UsernamePasswordToken token = new UsernamePasswordToken(user.getName(), user.getPassword());
try {
SecurityUtils.getSubject().login(token);
} catch (AuthenticationException e) {
redirectPath="/page/login.jsp";
return "redirect";
}
redirectPath="/page/index.jsp";
return "redirect";
}
//注销
public String loginout(){
SecurityUtils.getSubject().logout();
redirectPath="/login.jsp";
return "redirect";
}
至此基本结束,启动项目,就可以体验shiro的安全控制了 嘿嘿
下面说freemarker中使用shiro标签
这个网上一搜索就能找到答案,已经由James Gregory把代码上传到GitHub,
地址:https://github.com/jagregory/shiro-freemarker-tags
下载该jar包 或者源代码文件复制到自己工程的lib下或者package中
我是讲文件复制到自己的package中使用:
如果你使用spring MVC
请看http://www.woxplife.com/articles/473.html
如果你单独使用Freemarker 比如使用模板生成静态页
在相关的类中加入如下代码:
Configuration cfg = new Configuration();
cfg.setDefaultEncoding(“UTF-8”);
cfg.setSharedVariable("shiro", new ShiroTags());
然后在ftl页面中使用tag:
<@shiro.hasRole name=”admin”>Hello admin!</@shiro.hasRole>
如果是使用struts2集成的freemarker作为页面渲染
可以写一个类extend Struts2的FreemarkerManager:
import javax.servlet.ServletContext;
import org.apache.struts2.views.freemarker.FreemarkerManager;
import freemarker.template.Configuration;
import freemarker.template.TemplateException;
public class MyFreemarkerManager extends FreemarkerManager {
@Override
protected Configuration createConfiguration(ServletContext servletContext) throws TemplateException {
Configuration cfg = super.createConfiguration(servletContext);
cfg.setSharedVariable("shiro", new ShiroTags());
return cfg;
}
}
然后在struts.xml中指定struts使用我们自己扩展的 FreemarkerManager
<constant name="struts.freemarker.manager.classname"
value="com.xxx.xxx.MyFreemarkerManager" />
然后在页面中
然后在ftl页面中使用tag:
<@shiro.hasRole name=”admin”>Hello admin!</@shiro.hasRole>
周末这两天就学了这么多内容,希望有机会和大家探讨,共同进步!!!!
- 大小: 21.9 KB
- 大小: 4.7 KB
- 大小: 7.7 KB
- 大小: 8.1 KB
- 大小: 9.7 KB
分享到:
相关推荐
基于SpringBoot/WebFlux+Shiro+JPA+Java/Scala,实现的数据库细粒度动态权限管理系统(源码),项目经过严格测试,确保可以运行! 环境 SpringBoot 2.0.3.RELEASE SpringBoot WebFlux SpringBoot Data Jpa Apache ...
- Spring Boot 权限认证,包括 Apache Shiro、Spring Security - springboot-cloud - Spring Cloud 入门,包括 Eureka(服务注册与发现)、Config(配置中心)、Hystrix(断路器)、Bus(消息总线) 等
解决方案:在 FreeMarkerViewExtend.java 33行处 增加了BasePath ,通过BasePath 来控制请求目录,在 Freemarker 中可以自由使用,而 JSP 中是直接在 JSP 中获取BasePath 使用。 解决后遗症:因为我们的权限是通过...
J2eeFAST是一个Java EE企业级快速开发平台,基于经典技术组合(Spring Boot,Spring MVC,Apache Shiro,MyBatis-Plus,Freemarker,Bootstrap,AdminLTE)采用经典开发模式,让初学者能够Swift进行入门并从事在线...
权限: Apache Shiro 4.数据库以及连接池 数据库: MySQL 连接池:德鲁伊 5.杰森 Json转换: FastJson 6.前端技术 前端页面: FreeMarker模块引擎 前端样式: BootStrap 文件上传: ajaxFileUpload 文本编辑:百度...
权限框架:Apache Shiro 模板引擎:Freemarker 持久层框架:MyBatis 和 MyBatis-plus 数据库连接池:Alibaba Druid 缓存框架:J2cache、Redis 日志管理:LogBack 工具类:Apache Commons、HuTools 视图框架:Spring ...
spring4.04,springmvc, hibernate4.3 ,JPA2.1, shiro1.2, ehcache2 完全整合,用Ehcache做缓存,通用的DAO、Service接口和...Shiro的整合参考Kdboy《Apache Shiro 使用手册》、Mylove《案例教学整合配置》,感谢分享。
SpringWeb 架构(Maven+SpringMVC+SpringJDBC+Apache Shiro+Redis+MongoDB+EnCache+Freemarker+JSP)定位架构,借助Springside框架,好资源多分享
系统基于(Spring Boot、Spring MVC、Apache Shiro、MyBatis-Plus、Freemarker、Bootstrap、AdminLTE)经典技术开发, 系统内置核心模块包含众多常用基础功能(在线代码生成功能、组织机构、角色用户、菜单及按钮授权...
1、项目整合redis存储,shiro可使用redisSession可使用于集群访问 2、项目增加jwt模式 3、增加默认启动模式为开发模式 4、优化已知BUG SpringBootAdmin 微服务快速开发脚手架 平台简介 SpringBootAdmin是基于多个...
系统基于(Spring Boot、Spring MVC、Apache Shiro、MyBatis-Plus、Freemarker、Bootstrap、AdminLTE)经典技术开发, 系统内置核心模块包含众多常用基础功能(在线代码生成功能、组织机构、角色用户、菜单及按钮授权...
shiro-spring-1.2.3.jar shiro-web-1.2.3.jar sitemesh-2.4.2.jar slf4j-api-1.7.7.jar slf4j-log4j12-1.7.7.jar spring-aop-4.1.9.RELEASE.jar spring-beans-4.1.9.RELEASE.jar spring-context-4.1.9.RELEASE.jar ...
SpringBoot集成MyBatisPlus 技术选型: 核心框架:Spring Boot 1.5.1 安全框架:Apache Shiro 视图框架:Spring MVC 持久层框架:MyBatis MyBatisPlus 缓存技术:EhCache,Redis 数据库连接池:Druid 日志管理:SLF4J...
安全框架:Apache Shiro 1.4 持久层框架:Mybatis + mybatis plus 3.2.0 页面模板:Freemarker 缓存框架:Redis 数据库:mysql 消息队列:RabbitMq 分布式搜索:Elasticsearch 6.4.3 双工通讯协议:websocket 网络...
基于经典技术组合(Spring Boot、Spring MVC、Apache Shiro、MyBatis-Plus、Freemarker、Bootstrap、AdminLTE)采用经典开发模式,让初学者能够更快的入门并投入到团队开发中去。
安全框架:Apache Shiro 视图框架:Spring MVC 持久层框架:MyBatis MyBatisPlus 缓存技术:EhCache,Redis 数据库连接池:Druid 日志管理:SLF4J、Log4j 模版技术:FreeMarker 页面交互:BootStrap、Layer等
基于经典技术组合(Spring Boot、Spring MVC、Apache Shiro、MyBatis-Plus、Freemarker、Bootstrap、AdminLTE)采用经典开发模式,让初学者能够更快的入门并投入到团队开发中去。在线代码生成功能,包括核心模块如:...
Ajax-springboot-cms.zip,基于springboot、spring、springmvc、mybatis、freemarker、bootstrap、apache shiro、quartz、email、mysql等的内容管理系统。,ajax代表异步javascript和xml。它是多种web技术的集合,包括...