`

Apache Shiro 整合Spring 进行权限验证 以及在Freemarker中使用shiro标签

 
阅读更多
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
分享到:
评论
5 楼 等待时候 2017-07-18  
info.addStringPermissions( role.getPermissions() );


添加的是:[user:insert]
或者是:/user/insert

添加的哪个呢?
4 楼 onlyOneToOne 2014-01-20  
zqb666kkk 写道
principal标签怎么用?

正常用,可以去shiro官网看文档~!
3 楼 zqb666kkk 2014-01-07  
principal标签怎么用?
2 楼 onlyOneToOne 2013-09-24  
438608535 写道
写得可以~

1 楼 438608535 2013-09-23  
写得可以~

相关推荐

    freemarker的shiro标签

    1. **Shiro标签库**:Shiro提供了与FreeMarker集成的标签库,使得在FreeMarker模板中可以直接使用Shiro的权限控制功能。例如,`&lt;@shiro.hasPermission&gt;`标签可以用来判断当前用户是否有某个操作的权限,如果用户有...

    shiro-freemarker权限控制标签

    在实际应用中,你可以根据用户角色分配不同的权限,然后在模板中使用Shiro标签进行控制。例如,只有管理员角色的用户才能看到“删除用户”按钮: ```html &lt;#if shiro.hasPermission('delete:user')}&gt; ()"&gt;删除用户...

    springboot集成freemarker和shiro框架

    2. 使用Shiro标签:在模板中根据需要使用`shiro:hasPermission`、`shiro:principal`等标签进行权限控制和用户信息展示。 **六、示例应用** 在实际应用中,你可以创建一个简单的登录页面,用户输入用户名和密码,...

    springMVC+hibernate+spring+shiro整合例子

    同时,SpringMVC的Controller可以调用由Spring管理的Service层,而Service层则可以使用Hibernate进行数据操作,Shiro则在整个过程中提供安全控制。 通过这样的整合,我们可以构建出一个既能高效处理数据,又能提供...

    springmvc+freemarker+shiro

    在IT行业中,SpringMVC、FreeMarker和Shiro是三个非常重要的框架,它们分别负责不同的功能领域。SpringMVC作为Spring框架的一部分,主要用于构建Web应用程序的模型-视图-控制器(MVC)架构;FreeMarker则是一个强大...

    spring+springmvc+mybatis+shiro+freemarker+dubbo

    在这个项目中,Shiro可能用于实现用户登录验证、权限控制以及会话管理,确保系统的安全性。 5. **FreeMarker**:是一个模板引擎,用于生成动态HTML或其他文本格式的输出。在SpringMVC中,FreeMarker可以作为视图...

    shiro权限验证依赖包

    在Shiro中,FreeMarker可能用于生成动态的安全相关的视图,如登录页面或权限错误消息。 9. `spring-integration-core-4.0.5.RELEASE.jar`: 这是Spring Integration库,用于在不同系统之间实现低耦合的消息传递。...

    spring boot 集成 shiro 自定义密码验证 自定义freemarker标签根据权限渲染不同页面(推荐

    在这个示例中,我们将介绍如何将 Shiro 集成到 Spring Boot 项目中,并实现自定义密码验证和 Freemarker 标签根据权限渲染不同页面。 首先,需要在 pom.xml 文件中添加 Shiro 的依赖项: ```xml &lt;groupId&gt;org....

    JFinal2.0整合shiro权限框架,简单好用

    - **使用Shiro标签**:在视图层,可以利用Shiro的标签库,如`&lt;shiro:hasPermission&gt;`、`&lt;shiro:principal&gt;`等,动态展示或隐藏页面元素。 **4. 示例代码** 以下是一个简单的Shiro Realm示例: ```java public ...

    SpringBoot与Shiro整合-权限管理的简单权限系统.zip

    在这个项目中,Shiro用于处理用户登录验证,实现基于角色的权限控制,确保只有具有特定权限的用户才能访问相应的资源。 项目的核心流程可能包括以下几个步骤: 1. **用户注册与登录**:用户通过填写用户名和密码...

    SpringBoot+Spring data JPA+FreeMarker+shiro+log4jdbc

    综合上述技术,这个项目可能是一个使用SpringBoot作为基础框架,通过Spring Data JPA进行数据库操作,使用FreeMarker作为模板引擎展示页面,Shiro负责安全控制,而Log4jdbc则用于记录数据库查询日志的Web应用。...

    shiro-freemarker-springBoot- redis-mysql

    在本项目中,Shiro负责用户的身份验证(登录)、权限控制(访问控制)以及会话管理,确保只有经过验证的用户才能访问特定的资源。 **FreeMarker** FreeMarker是一个用于生成动态Web内容的模板引擎。它与Spring Boot...

    shiro整合SpringBoot

    - 如果项目使用了模板引擎,如 Thymeleaf 或 FreeMarker,Shiro 可以配合它们进行权限控制。例如,可以在模板文件中使用 Shiro 提供的 EL 函数 `sec:user?` 或 `sec:hasRole?` 来决定是否显示某些内容。 5. **API ...

    spring boot+jpa+cas+shiro

    这个项目集成了以上这些技术,构建了一个完整的示例应用,展示了如何在Spring Boot环境中使用JPA进行数据存储,通过CAS实现单点登录,利用Shiro进行权限控制,以及使用Freemarker来生成动态网页内容。这样的组合常见...

    Shiro + Hibernate5 + Spring5 + SpringMVC5 的jar

    标题中的"Shiro + Hibernate5 + Spring5 + SpringMVC5 的jar"指的是一个整合了四个关键Java技术的库文件,这些技术分别是Apache Shiro、Hibernate5、Spring5和SpringMVC5。这个压缩包可能包含了这四个框架的最新版本...

    权限管理系统(SpringMvc+Spring+MyBatis框架整合)

    在本项目中,我们基于SpringMvc、Spring和MyBatis三大主流Java技术栈进行了深度整合,构建了一个完整的权限管理系统。 **SpringMvc** 是Spring框架的一部分,主要用于Web应用的Model-View-Controller(MVC)架构...

    权限管理系统,基于Spring+SpringMvc+MiniJdbc+Shiro为架构的权限管理系统

    权限管理系统是企业信息化建设中的核心组件,它负责对用户、角色、资源以及它们之间的权限关系进行管理,确保系统安全稳定运行。本系统采用Spring、SpringMvc、MiniJdbc和Shiro四大核心技术构建,形成了一套高效、...

    SpringBoot + Shiro,单WEB项目的简单权限案例

    在IT行业中,SpringBoot和Apache Shiro是两个非常重要的框架,它们在构建现代Web应用程序时起着关键作用。本文将详细讲解如何结合SpringBoot与Shiro实现一个简单的权限管理案例。 首先,SpringBoot是由Pivotal团队...

    管理系统系列--Spring Boot &amp; Shiro 权限管理系统.zip

    通过学习和研究这个压缩包中的内容,开发者可以了解如何在Spring Boot项目中整合Shiro实现权限管理,这对于开发企业级应用尤其重要,因为它确保了系统的安全性,防止未授权的访问。同时,这也是提升个人技能和理解...

Global site tag (gtag.js) - Google Analytics