SpringMVC整合Shiro,Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能。

第一步:配置web.xml

<!-- 配置Shiro过滤器,先让Shiro过滤系统接收到的请求 --> 

<!-- 这里filter-name必须对应applicationContext.xml中定义的<bean id="shiroFilter"/> -->

<!-- 使用[/*]匹配所有请求,保证所有的可控请求都经过Shiro的过滤 -->

<!-- 通常会将此filter-mapping放置到最前面(即其他filter-mapping前面),以保证它是过滤器链中第一个起作用的 -->

<filter>

<filter-name>shiroFilter</filter-name>

<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

<init-param>

<!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 -->

<param-name>targetFilterLifecycle</param-name>

<param-value>true</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>shiroFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

第二步:配置applicationContext.xml

<!-- 继承自AuthorizingRealm的自定义Realm,即指定Shiro验证用户登录的类为自定义的ShiroDbRealm.java -->  

<bean id="myRealm" class="com.jadyer.realm.MyRealm"/>

<!-- Shiro默认会使用Servlet容器的Session,可通过sessionMode属性来指定使用Shiro原生Session -->

<!-- 即<property name="sessionMode" value="native"/>,详细说明见官方文档 -->

<!-- 这里主要是设置自定义的单Realm应用,若有多个Realm,可使用'realms'属性代替 -->

<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">

<property name="realm" ref="myRealm"/>
</bean>
<!-- Shiro主过滤器本身功能十分强大,其强大之处就在于它支持任何基于URL路径表达式的、自定义的过滤器的执行 -->

<!-- Web应用中,Shiro可控制的Web请求必须经过Shiro主过滤器的拦截,Shiro对基于Spring的Web应用提供了完美的支持 -->

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全接口,这个属性是必须的 -->

<property name="securityManager" ref="securityManager"/>
<!-- 要求登录时的链接(可根据项目的URL进行替换),非必须的属性,默认会自动寻找Web工程根目录下的"/login.jsp"页面 -->

<property name="loginUrl" value="/"/>
<!-- 登录成功后要跳转的连接(本例中此属性用不到,因为登录成功后的处理逻辑在LoginController里硬编码为main.jsp了) -->

<!-- <property name="successUrl" value="/system/main"/> -->

<!-- 用户访问未对其授权的资源时,所显示的连接 -->

<!-- 若想更明显的测试此属性可以修改它的值,如unauthor.jsp,然后用[玄玉]登录后访问/admin/listUser.jsp就看见浏览器会显示unauthor.jsp -->

<property name="unauthorizedUrl" value="/"/>
<!-- Shiro连接约束配置,即过滤链的定义 -->

<!-- 此处可配合我的这篇文章来理解各个过滤连的作用http://blog.csdn.net/jadyer/article/details/12172839 -->

<!-- 下面value值的第一个'/'代表的路径是相对于HttpServletRequest.getContextPath()的值来的 -->

<!-- anon:它对应的过滤器里面是空的,什么都没做,这里.do和.jsp后面的*表示参数,比方说login.jsp?main这种 -->

<!-- authc:该过滤器下的页面必须验证后才能访问,它是Shiro内置的一个拦截器org.apache.shiro.web.filter.authc.FormAuthenticationFilter -->

<property name="filterChainDefinitions">

<value>

/mydemo/login=anon

/mydemo/getVerifyCodeImage=anon

/main**=authc

/user/info**=authc

/admin/listUser**=authc,perms[admin:manage]

</value>

</property>

</bean>
<!-- 保证实现了Shiro内部lifecycle函数的bean执行 -->

<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

<!-- 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证 -->

<!-- 配置以下两个bean即可实现此功能 -->

<!-- Enable Shiro Annotations for Spring-configured beans. Only run after the lifecycleBeanProcessor has run -->

<!-- 由于本例中并未使用Shiro注解,故注释掉这两个bean(个人觉得将权限通过注解的方式硬编码在程序中,查看起来不是很方便,没必要使用) -->

<!--
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/>

<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">

<property name="securityManager" ref="securityManager"/>

</bean>

-->

第三步:自定义的Realm类

public class MyRealm extends AuthorizingRealm {  


/**

* 为当前登录的Subject授予角色和权限
* @see 经测试:本例中该方法的调用时机为需授权资源被访问时

* @see 经测试:并且每次访问需授权资源时都会执行该方法中的逻辑,这表明本例中默认并未启用AuthorizationCache

* @see 个人感觉若使用了Spring3.1开始提供的ConcurrentMapCache支持,则可灵活决定是否启用AuthorizationCache

* @see 比如说这里从数据库获取权限信息时,先去访问Spring3.1提供的缓存,而不使用Shior提供的AuthorizationCache

*/

@Override

protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals){

//获取当前登录的用户名,等价于(String)principals.fromRealm(this.getName()).iterator().next()

String currentUsername = (String)super.getAvailablePrincipal(principals);

// List<String> roleList = new ArrayList<String>();

// List<String> permissionList = new ArrayList<String>();

// //从数据库中获取当前登录用户的详细信息

// User user = userService.getByUsername(currentUsername);

// if(null != user){

// //实体类User中包含有用户角色的实体类信息

// if(null!=user.getRoles() && user.getRoles().size()>0){

// //获取当前登录用户的角色

// for(Role role : user.getRoles()){

// roleList.add(role.getName());

// //实体类Role中包含有角色权限的实体类信息

// if(null!=role.getPermissions() && role.getPermissions().size()>0){

// //获取权限

// for(Permission pmss : role.getPermissions()){

// if(!StringUtils.isEmpty(pmss.getPermission())){

// permissionList.add(pmss.getPermission());

// }

// }

// }

// }

// }

// }else{

// throw new AuthorizationException();

// }

// //为当前用户设置角色和权限

// SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();

// simpleAuthorInfo.addRoles(roleList);

// simpleAuthorInfo.addStringPermissions(permissionList);

SimpleAuthorizationInfo simpleAuthorInfo = new SimpleAuthorizationInfo();

//实际中可能会像上面注释的那样从数据库取得

if(null!=currentUsername && "mike".equals(currentUsername)){

//添加一个角色,不是配置意义上的添加,而是证明该用户拥有admin角色

simpleAuthorInfo.addRole("admin");

//添加权限

simpleAuthorInfo.addStringPermission("admin:manage");

System.out.println("已为用户[mike]赋予了[admin]角色和[admin:manage]权限");

return simpleAuthorInfo;

}

//若该方法什么都不做直接返回null的话,就会导致任何用户访问/admin/listUser.jsp时都会自动跳转到unauthorizedUrl指定的地址

//详见applicationContext.xml中的<bean id="shiroFilter">的配置

return null;

}


/**

* 验证当前登录的Subject

* @see 经测试:本例中该方法的调用时机为LoginController.login()方法中执行Subject.login()时

*/

@Override

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {

//获取基于用户名和密码的令牌

//实际上这个authcToken是从LoginController里面currentUser.login(token)传过来的

//两个token的引用都是一样的

UsernamePasswordToken token = (UsernamePasswordToken)authcToken;

System.out.println("验证当前Subject时获取到token为" + ReflectionToStringBuilder.toString(token, ToStringStyle.MULTI_LINE_STYLE));

// User user = userService.getByUsername(token.getUsername());

// if(null != user){

// AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), user.getNickname());

// this.setSession("currentUser", user);

// return authcInfo;

// }else{

// return null;

// }

//此处无需比对,比对的逻辑Shiro会做,我们只需返回一个和令牌相关的正确的验证信息

//说白了就是第一个参数填登录用户名,第二个参数填合法的登录密码(可以是从数据库中取到的,本例中为了演示就硬编码了)

//这样一来,在随后的登录页面上就只有这里指定的用户和密码才能通过验证

if("mike".equals(token.getUsername())){

AuthenticationInfo authcInfo = new SimpleAuthenticationInfo("mike", "mike", this.getName());

this.setSession("currentUser", "mike");

return authcInfo;

}

//没有返回登录用户名对应的SimpleAuthenticationInfo对象时,就会在LoginController中抛出UnknownAccountException异常

return null;

}

/**

* 将一些数据放到ShiroSession中,以便于其它地方使用

* @see 比如Controller,使用时直接用HttpSession.getAttribute(key)就可以取到

*/

private void setSession(Object key, Object value){

Subject currentUser = SecurityUtils.getSubject();

if(null != currentUser){

Session session = currentUser.getSession();

System.out.println("Session默认超时时间为[" + session.getTimeout() + "]毫秒");

if(null != session){

session.setAttribute(key, value);

}

}

}

}

Shiro 权限管理filterChainDefinitions过滤器配置

前言:shiro三大核心模块:Subject(用户)、SecurityManager(框架心脏)、Realm(Shiro与应用安全数据间的“桥梁”)

SecurityManager去管理cacheManager缓存和sessionManager会话,sessionManager再去管理sessionDAO会话DAO 和sessionIdCookie会话ID生成器和sessionValidationScheduler会话验证调度器,cacheManager通过使用Ehcache实现,Realm通过自己自定义或者其他方式的权限存储来实现,比如登录等.

使用统一数据访问层,通过编写实体类,编写Repository接口,最后通过配置文件实现

Repository是标识,spring自动扫描,CrudRepository继承Repository实现curd,PagingAndSortingRepository继承CrudRepository实现分页排序,JpaRepository继承PagingAndSortingRepository实现JPA规范相关的方法,JpaSpecificationExecutor不属于Repository,比较特殊,它去实现一组JPA Criteria查询相关的方法

/**

* Shiro-1.2.2内置的FilterChain

* @see =========================================================================================================

* @see 1)Shiro验证URL时,URL匹配成功便不再继续匹配查找(所以要注意配置文件中的URL顺序,尤其在使用通配符时)

* @see 故filterChainDefinitions的配置顺序为自上而下,以最上面的为准

* @see 2)当运行一个Web应用程序时,Shiro将会创建一些有用的默认Filter实例,并自动地在[main]项中将它们置为可用

* @see 自动地可用的默认的Filter实例是被DefaultFilter枚举类定义的,枚举的名称字段就是可供配置的名称

* @see anon—————org.apache.shiro.web.filter.authc.AnonymousFilter

* @see authc————–org.apache.shiro.web.filter.authc.FormAuthenticationFilter

* @see authcBasic———org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter

* @see logout————-org.apache.shiro.web.filter.authc.LogoutFilter

* @see noSessionCreation–org.apache.shiro.web.filter.session.NoSessionCreationFilter

* @see perms————–org.apache.shiro.web.filter.authz.PermissionAuthorizationFilter

* @see port—————org.apache.shiro.web.filter.authz.PortFilter

* @see rest—————org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter

* @see roles————–org.apache.shiro.web.filter.authz.RolesAuthorizationFilter

* @see ssl—————-org.apache.shiro.web.filter.authz.SslFilter

*@see user—————org.apache.shiro.web.filter.authz.UserFilter

* @see =========================================================================================================

* @see 3)通常可将这些过滤器分为两组

* @see anon,authc,authcBasic,user是第一组认证过滤器

* @see perms,port,rest,roles,ssl是第二组授权过滤器

* @see 注意user和authc不同:当应用开启了rememberMe时,用户下次访问时可以是一个user,但绝不会是authc,因为authc是需要重新认证的

* @see user表示用户不一定已通过认证,只要曾被Shiro记住过登录状态的用户就可以正常发起请求,比如rememberMe

* @see 说白了,以前的一个用户登录时开启了rememberMe,然后他关闭浏览器,下次再访问时他就是一个user,而不会authc

* @see ==========================================================================================================

* @see 4)举几个例子

* @see /admin=authc,roles[admin] 表示用户必需已通过认证,并拥有admin角色才可以正常发起’/admin’请求

* @see /edit=authc,perms[admin:edit] 表示用户必需已通过认证,并拥有admin:edit权限才可以正常发起’/edit’请求

* @see /home=user 表示用户不一定需要已经通过认证,只需要曾经被Shiro记住过登录状态就可以正常发起’/home’请求

* @see ==========================================================================================================

* @see 5)各默认过滤器常用如下(注意URL Pattern里用到的是两颗星,这样才能实现任意层次的全匹配)

* @see /admins/**=anon 无参,表示可匿名使用,可以理解为匿名用户或游客

* @see /admins/user/**=authc 无参,表示需认证才能使用

* @see /admins/user/**=authcBasic 无参,表示httpBasic认证

* @see /admins/user/**=user 无参,表示必须存在用户,当登入操作时不做检查

* @see /admins/user/**=ssl 无参,表示安全的URL请求,协议为https

* @see /admins/user/*=perms[user:add:]

* @see 参数可写多个,多参时必须加上引号,且参数之间用逗号分割,如/admins/user/*=perms[“user:add:,user:modify:*”]

* @see 当有多个参数时必须每个参数都通过才算通过,相当于isPermitedAll()方法

* @see /admins/user/**=port[8081]

* @see 当请求的URL端口不是8081时,跳转到schemal://serverName:8081?queryString

* @see 其中schmal是协议http或https等,serverName是你访问的Host,8081是Port端口,queryString是你访问的URL里的?后面的参数

* @see /admins/user/**=rest[user]

* @see 根据请求的方法,相当于/admins/user/**=perms[user:method],其中method为post,get,delete等

* @see /admins/user/**=roles[admin]

* @see 参数可写多个,多个时必须加上引号,且参数之间用逗号分割,如/admins/user/**=roles[“admin,guest”]

* @see 当有多个参数时必须每个参数都通过才算通过,相当于hasAllRoles()方法

* @see

http://liureying.blog.163.com/blog/static/61513520136205574873/

spring中 shiro logout 配置方式

有两种方式实现logout

1. 普通的action中 实现自己的logout方法,取到Subject,然后logout

这种需要在ShiroFilterFactoryBean 中配置 filterChainDefinitions

对应的action的url为a



# some example chain definitions:

/index.htm = anon

/logout = anon

/unauthed = anon

/console/** = anon

/css/** = anon

/js/** = anon

/lib/** = anon

/admin/** = authc, roles[admin]

/docs/** = authc, perms[document:read]

/** = authc

# more URL-to-FilterChain definitions here

使用shiro提供的logout filter

需要定义 相应的bean

然后将相应的url filter配置为logout如下

<property name="filterChainDefinitions">

<value>
# some example chain definitions:

/index.htm = anon

/logout = logout
/unauthed = anon

/console/** = anon

/css/** = anon

/js/** = anon

/lib/** = anon

/admin/** = authc, roles[admin]

/docs/** = authc, perms[document:read]

/** = authc

# more URL-to-FilterChain definitions here

</value>

注:anon,authcBasic,auchc,user是认证过滤器,perms,roles,ssl,rest,port是授权过滤器

最终 各种参数配置详解

anon:例子/admins/**=anon 没有参数,表示可以匿名使用。

authc:例如/admins/user/**=authc表示需要认证(登录)才能使用,没有参数

roles:例子/admins/user/=roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如admins/user/=roles[“admin,guest”],每个参数通过才算通过,相当于hasAllRoles()方法。

perms:例子/admins/user/=perms[user:add:],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/=perms[“user:add:,user:modify:*”],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。

rest:例子/admins/user/=rest[user],根据请求的方法,相当于/admins/user/=perms[user:method] ,其中method为post,get,delete等。

port:例子/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString

是你访问的url里的?后面的参数。

authcBasic:例如/admins/user/**=authcBasic没有参数表示httpBasic认证

ssl:例子/admins/user/**=ssl没有参数,表示安全的url请求,协议为https

user:例如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查

注:anon,authcBasic,auchc,user是认证过滤器,

perms,roles,ssl,rest,port是授权过滤器

SpringMVC整合Shiro,Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能的更多相关文章

  1. SpringMVC整合Apache Shiro

    关于什么是Shiro,可以查看这篇文章http://www.cnblogs.com/Laymen/articles/6117751.html 一.添加maven依赖 <dependency> ...

  2. 部署用于生产的Exceptionlees(一个强大易用的日志收集服务)

    Exceptionless是一个非常优秀的事件记录服务,目前我们的自部署的Exceptionless已经稳定运行了近一年的时间,收集了千万条事件信息.但Exceptionless官方自宿主部署的文档不 ...

  3. SpringMVC整合Shiro——(3)

    SpringMVC整合Shiro,Shiro是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理等功能. 第一步:配置web.xml <!-- 配置Shiro过滤器,先让Shiro ...

  4. SpringMVC整合Shiro权限框架

    尊重原创:http://blog.csdn.net/donggua3694857/article/details/52157313 最近在学习Shiro,首先非常感谢开涛大神的<跟我学Shiro ...

  5. 源码分析shiro认证授权流程

    1. shiro介绍 Apache Shiro是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理等功能: 认证 - 用户身份识别,常被称为用户“登录”: 授权 - 访问控制: 密码加密 ...

  6. Apache Shiro java安全框架

    什么是Apache Shiro? Apache Shiro(发音为“shee-roh”,日语“堡垒(Castle)”的意思)是一个强大易用的Java安全框架,提供了认证.授权.加密和会话管理功能,可为 ...

  7. Shiro - 轻量级Java 安全框架

    Apache Shiro 是一个强大易用的 Java 安全框架,提供了认证.授权.加密和会话管理等功能,对于任何一个应用程序,Shiro 都可以提供全面的安全管理服务. 并且相对于其他安全框架,Shi ...

  8. SpringMVC整合Shiro安全框架(一)

    一. 准备工作 1. 本文参考自张开涛的 <跟我学Shiro> 二. 简介 1. Apache Shiro是Java的一个安全框架.可以帮助我们完成:认证.授权.加密.会话管理.与Web集 ...

  9. 跟开涛老师学shiro -- shiro简介

    1.1  简介 Apache Shiro是Java的一个安全框架.目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring Security,可能没有Spring Securi ...

随机推荐

  1. [Python] Find available methods and help in REPL

    For example you want to know what methods are available in Python for String, you can do : dir(" ...

  2. 【Linux探索之旅】第四部分第三课:文件传输,潇洒同步

    内容简单介绍 .第四部分第三课:文件传输.潇洒同步 2.第四部分第四课:分析网络.隔离防火 文件传输.潇洒同步 这一课的内容相对简单,所以我们慢慢享用. 经过上一课的学习.我们已经知道怎样远程连接到其 ...

  3. CocoaPods制作

    欢迎相同喜欢动效的工程师/UI设计师/产品添加我们 iOS动效特攻队–>QQ群:547897182 iOS动效特攻队–>熊熊:648070256 引言: 折腾了三四天,各种文章翻遍了,遇到 ...

  4. spark资料下载

    很全的spark资料下载,包含pdf书籍和培训学校视频教程, 1.spark多语言编程:spark多语言开发 2.tachyon:tachyon 3.sparkR:sparkR 所有内容请点击:所有内 ...

  5. MySql 存储引擎的选取

    存储引擎是为不同的表类型处理 SQL 操作的 MySql 组件.InnoDB 是默认的.最通用的存储引擎,也是官方推荐使用的存储引擎,除非一些特定案例.MySql 5.6 中的 CREATE TABL ...

  6. Codefroces Educational Round 26 837 D. Round Subset

    D. Round Subset time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  7. Spring--之旅

    spring的地位 如图可以看出,sping纵跨整个项目架构,它是一个容器框架.下面使用一个简单的项目来认识spring. 快速入门 step 1.新建一个普通Java工程,spring只是一种容器, ...

  8. netstat---显示Linux中网络系统的状态信息

    netstat命令用来打印Linux中网络系统的状态信息,可让你得知整个Linux系统的网络情况. 语法 netstat(选项) 选项 -a或--all:显示所有连线中的Socket: -A<网 ...

  9. Tomcat之——配置项目有虚拟路径

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/47024863 非常easy,在Tomcat的Server.xml文件里的Host节 ...

  10. 9.使用 npm 命令安装模块

    转自:http://www.runoob.com/nodejs/nodejs-tutorial.html npm 安装 Node.js 模块语法格式如下: $ npm install <Modu ...