JeeSite 对配置说明

本文介绍Apache Shiro框架的配置与应用,包括安全认证过滤器、FormAuthenticationFilter类、SystemAuthorizingRealm类及LoginController类的工作原理。
摘要由CSDN通过智能技术生成

Apache Shiro的配置主要分为四部分: 

  • 对象和属性的定义与配置
  • URL的过滤器配置
  • 静态用户配置
  • 静态角色配置
其中,由于用户、角色一般由后台进行操作的动态数据,因此Shiro配置一般仅包含前两项的配置。 

Apache Shiro的大多数组件是基于POJO的,因此我们可以使用POJO兼容的任何配置机制进行配置,例如:Java代码、Sping XML、YAML、JSON、ini文件等等。下面,以Spring XML的配置方式为例,并且对其中的一些配置参数进行一些简单说明。 

Shiro对象的配置:  
主要是对Shiro各个组件的实现进行定义配置,主要组件在前文已做过简单介绍,这里不再一一说明。 
  1. <bean id="securityManager" class="org.apache.shiro.mgt.DefaultSecurityManager">  
  2.         <property name="cacheManager" ref="cacheManager"/>  
  3.         <property name="sessionMode" value="native"/>  
  4.         <!-- Single realm app.  If you have multiple realms, use the 'realms' property instead. -->  
  5.         <property name="realm" ref="myRealm"/>  
  6.         <property name="sessionManager" ref="sessionManager"/>   
  7. </bean>  


Shiro过滤器的配置  
Shiro主要是通过URL过滤来进行安全管理,这里的配置便是指定具体授权规则定义。 
  1. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
  2.     <property name="securityManager" ref="securityManager"/>  
  3.     <property name="loginUrl" value="/login.jsp"/>  
  4.     <property name="successUrl" value="/home.jsp"/>  
  5.     <property name="unauthorizedUrl" value="/unauthorized.jsp"/> -->  
  6.     <property name="filterChainDefinitions">  
  7.         <value>  
  8.             # some example chain definitions:  
  9.             /admin/** = authc, roles[admin]  
  10.             /docs/** = authc, perms[document:read]  
  11.             /** = authc  
  12.             # more URL-to-FilterChain definitions here  
  13.         </value>  
  14.     </property>  
  15. </bean>  

URL过滤器配置说明:  
Shiro可以通过配置文件实现基于URL的授权验证。FilterChain定义格式: 
URL_Ant_Path_Expression = Path_Specific_Filter_Chain 
每个URL配置,表示匹配该URL的应用程序请求将由对应的过滤器进行验证。 
例如: 
[urls] 
/index.html = anon 
/user/create = anon 
/user/** = authc 
/admin/** = authc, roles[administrator] 
/rest/** = authc, rest 
/remoting/rpc/** = authc, perms["remote:invoke"] 

URL表达式说明  
1、URL目录是基于HttpServletRequest.getContextPath()此目录设置 
2、URL可使用通配符,**代表任意子目录 
3、Shiro验证URL时,URL匹配成功便不再继续匹配查找。所以要注意配置文件中的URL顺序,尤其在使用通配符时。 

Filter Chain定义说明  
1、一个URL可以配置多个Filter,使用逗号分隔 
2、当设置多个过滤器时,全部验证通过,才视为通过 
3、部分过滤器可指定参数,如perms,roles 

Shiro内置的FilterChain  

Filter Name Class
anon org.apache.shiro.web.filter.authc.AnonymousFilter
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
port org.apache.shiro.web.filter.authz.PortFilter
rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
ssl org.apache.shiro.web.filter.authz.SslFilter
user org.apache.shiro.web.filter.authc.UserFilter





补充:


 Apache Shiro 提供了一个可用的安全性框架,各种客户机都可将这个框架应用于它们的应用程序。本文中的这些例子旨在介绍 Shiro 并着重展示对用户进行身份验证的基本任务。
本文只针对Jeesite中shiro的用法进行整理,不会包括shiro环境配置和搭建等内容。

Jeesite中的shiro

2.1 spring-context-shiro.xml

    spring-context-shiro.xml是shiro的主配置文件,配置信息是重点主要是安全认证过滤器的配置。它规定哪些url需要进行哪些方面的认证和过滤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- 安全认证过滤器 -->
< bean id = "shiroFilter" class = "org.apache.shiro.spring.web.ShiroFilterFactoryBean" >
     < property name = "securityManager" ref = "securityManager" />
     < property name = "p" value = "${adminPath}/login" />
     < property name = "successUrl" value = "${adminPath}" />
     < property name = "filters" >
         < map >
             < entry key = "authc" value-ref = "formAuthenticationFilter" />
         </ map >
     </ property >
     < property name = "filterChainDefinitions" >
         < value >
             /static/** = anon
             /userfiles/** = anon
             ${adminPath}/login = authc
             ${adminPath}/logout = logout
             ${adminPath}/** = user
         </ value >
     </ property >
</ bean >

    shiroFilter是shiro的安全认证过滤器,其中,

  • securityManager:指定一个负责管理的bean,这个新的bean在接下来会定义,其中包含了认证的主要逻辑。
  • loginUrl:没有登录的用户请求需要登录的页面时自动跳转到登录页面,不是必须的属性,不输入地址的话会自动寻找项目web项目的根目录下的”/login.jsp”页面。
  • successUrl:登录成功默认跳转页面,不配置则跳转至”/”。如果登陆前点击的一个需要登录的页面,则在登录自动跳转到那个需要登录的页面。不跳转到此。
  • unauthorizedUrl:没有权限默认跳转的页面。
  • map中的entry指定了authc权限所对应的过滤器实体

而属性中的filterChainDefinitions则详细规定啦不同的url的对应权限

  • 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是授权过滤器
1
2
3
4
5
6
7
<!-- 定义 Shiro 主要业务对象 -->
<bean id="securityManager"
class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- <property name="sessionManager" ref="sessionManager" /> -->
<property name="realm" ref="systemAuthorizingRealm" />
<property name="cacheManager" ref="shiroCacheManager" />
</bean>

    这部分代码定义了securitymanager的主要属性的实体,systemAuthorizingRealm和shiroCacheManager都是自己实现的,分别用于进行验证管理和cache管理。从配置文件能看出,配置文件指定了作为安全逻辑的几个结构,除了这两部分,还包括formAuthenticationFilter。其中realm和filter在com.thinkgem.jeesite.modules.sys.security包里实现。

2.2 FormAuthenticationFilter

    从可见都逻辑上讲,FormAuthenticationFilter类是用户验证时所接触的第一个类。
    当用户登录任意界面时,shiro会对当前状态进行检查。如果发现需要登录,则会自动跳转到配置文件里loginUrl属性所指定的url中。
    而这一url又被指定为authc权限,即需要验证。接着,authc的filter被指定为formAuthenticationFilter,因此login页面所提交的信息被改filter截获进行处理。
    其中的核心逻辑是createToken函数:

1
2
3
4
5
6
7
8
9
10
11
protected AuthenticationToken createToken(S2ervletRequest request, ServletResponse response) {
     String username = getUsername(request);
     String password = getPassword(request);
     if (password== null ){
         password = "" ;
     }
     boolean rememberMe = isRememberMe(request);
     String host = getHost(request);
     String captcha = getCaptcha(request);
     return new UsernamePasswordToken(username, password.toCharArray(), rememberMe, host, captcha);
}

    UsernamePasswordToken是security包里的第四个类,它继承自shiro的同名类,用于shiro处理中的参数传递。createtoken函数接受到login网页所接受的表单,生成一个token传给下一个类处理。
    函数中的rememberme以及captcha分别表示的是记住用户功能和验证码功能,这部分也是shiro自身携带,我们并不需要修改。filter是通过aop的方式结合到系统里的,因此并没有具体的接口实现。

2.3 SystemAuthorizingRealm

    shiro的最终处理都将交给Real进行处理。因为在Shiro中,最终是通过Realm来获取应用程序中的用户、角色及权限信息的。通常情况下,在Realm中会直接从我们的数据源中获取Shiro需要的验证信息。可以说,Realm是专用于安全框架的DAO.
Realm中有个参数是systemService,这个便是spring的具体业务逻辑,其中也包含了具体的DAO,正是在这个部分,shiro与spring的接口具体的结合了起来。
realm当中有两个函数特别重要,分别是用户认证函数和授权函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
     UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
     
     if (LoginController.isValidateCodeLogin(token.getUsername(), false, false)){
         // 判断验证码
         Session session = SecurityUtils.getSubject().getSession();
         String code = (String)session.getAttribute(ValidateCodeServlet.VALIDATE_CODE);
         if (token.getCaptcha() == null || !token.getCaptcha().toUpperCase().equals(code)){
             throw new CaptchaException("验证码错误.");
         }
     }
 
     User user = getSystemService().getUserByLoginName(token.getUsername());
     if (user != null) {
         byte[] salt = Encodes.decodeHex(user.getPassword().substring(0,16));
         return new SimpleAuthenticationInfo(new Principal(user),
                 user.getPassword().substring(16), ByteSource.Util.bytes(salt), getName());
     } else {
         return null;
     }
}

    以上便是用户认证函数,中间关于验证码检测的部分我们暂且不表,其最核心的语句是

1
2
3
User user = getSystemService().getUserByLoginName(token.getUsername());
以及另一句语句
return new SimpleAuthenticationInfo(new Principal(user), user.getPassword().substring(16), ByteSource.Util.bytes(salt), getName());

    函数的参数AuthenticationToken便是filter所截获并生成的token实例,其内容是login表单里的内容,通常是用户名和密码。在前一句话里,getSystemService取到了systemService实例,该实例中又含有配置好的userDAO,能够直接与数据库交互。因此将用户id传入,取出数据库里所存有的user实例,接着在SimpleAuthenticationInfo生成过程中分别以user实例的用户名密码,以及token里的用户名密码做为参数,验证密码是否相同,以达到验证的目的。
    doGetAuthorizationInfo函数是授权的函数,其具体的权限是在实现类中以annotation的形式指派的,它负责验证用户是否有权限访问。详细的细节容我之后添加。

2.3 LoginController

     LoginController是本该实现登录认证的部分。由于shiro的引入和AOP的使用,jeesite中的LoginController只处理验证之后的部分。
如果通过验证,系统中存在user实例,则返回对应的主页。否则重新定位于login页面。

2.4 annotation

    常用的annotation主要如下:

  • @RequiresAuthentication
        要求当前Subject 已经在当前的session 中被验证通过才能被注解的类/实例/方法访问或调用。
        验证用户是否登录,等同于方法subject.isAuthenticated() 结果为true时。

  • @RequiresUser
        需要当前的Subject 是一个应用程序用户才能被注解的类/实例/方法访问或调用。要么是通过验证被确认,或者在之前session 中的'RememberMe'服务被记住。
        验证用户是否被记忆,user有两种含义:一种是成功登录的(subject.isAuthenticated() 结果为true);另外一种是被记忆的(subject.isRemembered()结果为true)。

  • @RequiresGuest
        要求当前的Subject 是一个“guest”,也就是他们必须是在之前的session中没有被验证或记住才能被注解的类/实例/方法访问或调用。
        验证是否是一个guest的请求,与@RequiresUser完全相反。
        换言之,RequiresUser == !RequiresGuest。此时subject.getPrincipal() 结果为null.

  • @RequiresRoles
        要求当前的Subject 拥有所有指定的角色。如果他们没有,则该方法将不会被执行,而且AuthorizationException 异常将会被抛出。例如:@RequiresRoles("administrator")
    或者@RequiresRoles("aRoleName");
    void someMethod();
        如果subject中有aRoleName角色才可以访问方法someMethod。如果没有这个权限则会抛出异常AuthorizationException。

  • @RequiresPermissions
        要求当前的Subject 被允许一个或多个权限,以便执行注解的方法,比如:
        @RequiresPermissions("account:create")
        或者@RequiresPermissions({"file:read", "write:aFile.txt"} )
        void someMethod();






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值