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对Shrio的标签还不支持,不过已经有人贡献出来第三方面解决方案,如下:
1、下载shiro-freemarker-tags
GitHub地址:https://github.com/jagregory/shiro-freemarker-tags
可以先看一下他的说明文档,有一个初步的了解。
2、Spring MVC配置
自定义一个ShiroTagFreeMarkerConfigurer继承Spring本身提供的FreeMarkerConfigurer,目的是在FreeMarker的Configuration中添加shiro的配置
public class ShiroTagFreeMarkerConfigurer extends FreeMarkerConfigurer { @Override public void afterPropertiesSet() throws IOException, TemplateException { super.afterPropertiesSet(); this.getConfiguration().setSharedVariable("shiro", new ShiroTags()); } }
下面的Spring mvc配置
<bean id="freemakerCongfig" class="com.xxx.web.freemarker.ShiroTagFreeMarkerConfigurer"> <property name="templateLoaderPath" value="/WEB-INF/views/" /> <property name="freemarkerSettings"> <props> <prop key="defaultEncoding">UTF-8</prop> <prop key="classic_compatible">true</prop> </props> </property> </bean>
3、使用Shiro Tag
<@shiro.guest>Hello guest!</@shiro.guest>
二:如果你单独使用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>
相关推荐
1. **Shiro标签库**:Shiro提供了与FreeMarker集成的标签库,使得在FreeMarker模板中可以直接使用Shiro的权限控制功能。例如,`<@shiro.hasPermission>`标签可以用来判断当前用户是否有某个操作的权限,如果用户有...
在实际应用中,你可以根据用户角色分配不同的权限,然后在模板中使用Shiro标签进行控制。例如,只有管理员角色的用户才能看到“删除用户”按钮: ```html <#if shiro.hasPermission('delete:user')}> ()">删除用户...
2. 使用Shiro标签:在模板中根据需要使用`shiro:hasPermission`、`shiro:principal`等标签进行权限控制和用户信息展示。 **六、示例应用** 在实际应用中,你可以创建一个简单的登录页面,用户输入用户名和密码,...
同时,SpringMVC的Controller可以调用由Spring管理的Service层,而Service层则可以使用Hibernate进行数据操作,Shiro则在整个过程中提供安全控制。 通过这样的整合,我们可以构建出一个既能高效处理数据,又能提供...
在IT行业中,SpringMVC、FreeMarker和Shiro是三个非常重要的框架,它们分别负责不同的功能领域。SpringMVC作为Spring框架的一部分,主要用于构建Web应用程序的模型-视图-控制器(MVC)架构;FreeMarker则是一个强大...
在这个项目中,Shiro可能用于实现用户登录验证、权限控制以及会话管理,确保系统的安全性。 5. **FreeMarker**:是一个模板引擎,用于生成动态HTML或其他文本格式的输出。在SpringMVC中,FreeMarker可以作为视图...
在Shiro中,FreeMarker可能用于生成动态的安全相关的视图,如登录页面或权限错误消息。 9. `spring-integration-core-4.0.5.RELEASE.jar`: 这是Spring Integration库,用于在不同系统之间实现低耦合的消息传递。...
在这个系统中,Shiro用于用户登录认证和权限控制,确保只有经过验证的用户才能访问特定资源,同时实现角色和权限的细粒度管理。 4. **Layui**: Layui是一个轻量级的前端UI框架,提供了一系列精美的组件,如表格、...
在这个示例中,我们将介绍如何将 Shiro 集成到 Spring Boot 项目中,并实现自定义密码验证和 Freemarker 标签根据权限渲染不同页面。 首先,需要在 pom.xml 文件中添加 Shiro 的依赖项: ```xml <groupId>org....
- **使用Shiro标签**:在视图层,可以利用Shiro的标签库,如`<shiro:hasPermission>`、`<shiro:principal>`等,动态展示或隐藏页面元素。 **4. 示例代码** 以下是一个简单的Shiro Realm示例: ```java public ...
在这个项目中,Shiro用于处理用户登录验证,实现基于角色的权限控制,确保只有具有特定权限的用户才能访问相应的资源。 项目的核心流程可能包括以下几个步骤: 1. **用户注册与登录**:用户通过填写用户名和密码...
综合上述技术,这个项目可能是一个使用SpringBoot作为基础框架,通过Spring Data JPA进行数据库操作,使用FreeMarker作为模板引擎展示页面,Shiro负责安全控制,而Log4jdbc则用于记录数据库查询日志的Web应用。...
在本项目中,Shiro负责用户的身份验证(登录)、权限控制(访问控制)以及会话管理,确保只有经过验证的用户才能访问特定的资源。 **FreeMarker** FreeMarker是一个用于生成动态Web内容的模板引擎。它与Spring Boot...
- 如果项目使用了模板引擎,如 Thymeleaf 或 FreeMarker,Shiro 可以配合它们进行权限控制。例如,可以在模板文件中使用 Shiro 提供的 EL 函数 `sec:user?` 或 `sec:hasRole?` 来决定是否显示某些内容。 5. **API ...
这个项目集成了以上这些技术,构建了一个完整的示例应用,展示了如何在Spring Boot环境中使用JPA进行数据存储,通过CAS实现单点登录,利用Shiro进行权限控制,以及使用Freemarker来生成动态网页内容。这样的组合常见...
标题中的"Shiro + Hibernate5 + Spring5 + SpringMVC5 的jar"指的是一个整合了四个关键Java技术的库文件,这些技术分别是Apache Shiro、Hibernate5、Spring5和SpringMVC5。这个压缩包可能包含了这四个框架的最新版本...
在本项目中,我们基于SpringMvc、Spring和MyBatis三大主流Java技术栈进行了深度整合,构建了一个完整的权限管理系统。 **SpringMvc** 是Spring框架的一部分,主要用于Web应用的Model-View-Controller(MVC)架构...
权限管理系统是企业信息化建设中的核心组件,它负责对用户、角色、资源以及它们之间的权限关系进行管理,确保系统安全稳定运行。本系统采用Spring、SpringMvc、MiniJdbc和Shiro四大核心技术构建,形成了一套高效、...
在IT行业中,SpringBoot和Apache Shiro是两个非常重要的框架,它们在构建现代Web应用程序时起着关键作用。本文将详细讲解如何结合SpringBoot与Shiro实现一个简单的权限管理案例。 首先,SpringBoot是由Pivotal团队...