• shiro(2)架构与配置


    认证就是用户确认身份的过程,确认登录的用户身份能够操作的内容。

    使用shiro认证分为以下几个步骤:

    1,得到主体的认证和凭据。

    // let's login the current user so we can check against roles and permissions:
            if (!currentUser.isAuthenticated()) {
                UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
                token.setRememberMe(true);
    

    2,提交认证和凭据给身份验证系统。

    Subject currentUser = SecurityUtils.getSubject();
    currentUser.login(token);
    

    3,判断是否允许访问,重试认证或者阻止访问。

    try {
                    currentUser.login(token);
                } catch (UnknownAccountException uae) {
                    log.info("There is no user with username of " + token.getPrincipal());
                } catch (IncorrectCredentialsException ice) {
                    log.info("Password for account " + token.getPrincipal() + " was incorrect!");
                } catch (LockedAccountException lae) {
                    log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                            "Please contact your administrator to unlock it.");
                }
                // ... catch more exceptions here (maybe custom ones specific to your application?
                catch (AuthenticationException ae) {
                    //unexpected condition?  error?
                }
    

    其中Remember Me的功能包括两个方法,一个是

    isRemembered

    boolean isRemembered()
    非匿名登录的用户可以记住上次使用的主题的信息。

    isAuthenticated

    boolean isAuthenticated()
    在此期间需要使用有效的凭据登录系统,否则值为false.
     
    授权操作
    授权的例子就是是否可以访问某个页面,可以操作某个按钮,是否可以编缉对应的数据等。
    如何在shiro中使用授权
    1,使用编程方式
    判断是否有管理员角色
    if (currentUser.hasRole("admin")) {
    
    判断用户是否有打印的权限
    Permission printPermission = new PrinterPermission(“laserjet3000n”,“print”);
    If (currentUser.isPermitted(printPermission)) {
        //do one thing (show the print button?)‏
    } else {
        //don’t show the button?
    }

    也可以使用字符串的方式验证

    String perm = “printer:print:laserjet4400n”;
    
    if(currentUser.isPermitted(perm)){
        //show the print button?
    } else {
        //don’t show the button?
    }
    2,使用注释方式
     判断用户是否有 创建账户权限
    //Will throw an AuthorizationException if none
    //of the caller’s roles imply the Account 
    //'create' permission\u000B
    @RequiresPermissions(“account:create”)‏
    public void openAccount( Account acct ) { 
        //create the account
    }
    
    判断用户角色,如果符合角色,可以使用对应方法
    //Throws an AuthorizationException if the caller
    //doesn’t have the ‘teller’ role:
    
    @RequiresRoles( “teller” )
    public void openAccount( Account acct ) { 
        //do something in here that only a teller
        //should do
    }
    
    3,使用jsp taglib
     判断用户是否有管理权限
    <%@ taglib prefix=“shiro” uri=http://shiro.apache.org/tags %>
    <html>
    <body>
        <shiro:hasPermission name=“users:manage”>
            <a href=“manageUsers.jsp”>
                Click here to manage users
            </a>
        </shiro:hasPermission>
        <shiro:lacksPermission name=“users:manage”>
            No user management for you!
        </shiro:lacksPermission>
    </body>
    </html>
    
     
    从高的级别来看shiro:
    看一下官方的图

    应用程序调用subject(主题),主题可以是一个用户也可以是与系统交互的另一个系统,主题绑定shiro的权限管理,SecurityManager(安全管理),它控制与有与主题相关的安全操作。Realm(桥梁)它是安全与数据之间的桥,它封装了比如DAO的配置信息,可以指定连接的数据源,也可使用其它的认证方式,如LDAP等。

    然后看一下详细的架构图:

    Subject (org.apache.shiro.subject.Subject)

    主题:与系统交互的第三方如(用户,cron服务,第三方应用)等。

    SecurityManager (org.apache.shiro.mgt.SecurityManager)

    shiro系统的核心,协调主题使用的操作,验证,配置等。

    Authenticator (org.apache.shiro.authc.Authenticator)

    身份验证组件,对企图登录系统的用户进行身份的验证。其中包含一个Authentication Strategy

     (org.apache.shiro.authc.pam.AuthenticationStrategy)组件。配置验证成功与失败的条件。

    Authorizer (org.apache.shiro.authz.Authorizer)

    授权组件,指用户访问特定应用程序的机制。

    SessionManager (org.apache.shiro.session.mgt.SessionManager)

    管理会话如何创建生命周期。其中包括的sessiondao是管理会议数据的持久操作:SessionDAO (org.apache.shiro.session.mgt.eis.SessionDAO),代表执行sessionManager的CRUD操作。

    CacheManager (org.apache.shiro.cache.CacheManager)

    缓存管理模块。

    Cryptography (org.apache.shiro.crypto.*)

    加密模块。

    Realms (org.apache.shiro.realm.Realm)

    多种方式处理的桥梁。

    多种配置方式:

    与spring,jboss,guice等进行配置。

    1,编程方式配置

    例如:

    Realm realm = //instantiate or acquire a Realm instance.  We'll discuss Realms later.
    
    SecurityManager securityManager = new DefaultSecurityManager(realm);
    //Make the SecurityManager instance available to the entire application via static memory:
    SecurityUtils.setSecurityManager(securityManager);
    

    2,sessionManager对象图

    如果你想使用sessionManager配置自定义的sessionDao信息,进行自定义会话管理

    ...
    
    DefaultSecurityManager securityManager = new DefaultSecurityManager(realm);
    SessionDAO sessionDAO = new CustomSessionDAO();
    
    ((DefaultSessionManager)securityManager.getSessionManager()).setSessionDAO(sessionDAO);
    ...
    

    3,INI配置

    1) 创建一个INI从SecurityManager

    可以从多种方式读取INI配置文件的信息,如文件系统,类路径等

    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.util.Factory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    ...
    
    Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
    SecurityManager securityManager = factory.getInstance();
    SecurityUtils.setSecurityManager(securityManager);
    

    2) 通过Ini实例读取

    类似于Properties的方式

    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.util.Factory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.config.Ini;
    import org.apache.shiro.config.IniSecurityManagerFactory;
    ...
    
    Ini ini = new Ini();
    //populate the Ini instance as necessary
    ...
    Factory<SecurityManager> factory = new IniSecurityManagerFactory(ini);
    SecurityManager securityManager = factory.getInstance();
    SecurityUtils.setSecurityManager(securityManager);
    

    加载之后就可以操作INI的配置了。

    4,INI配置

    每一个节点都是单独的,不可以重复,注释可以使用#或者;

    配置示例

    # =======================
    # Shiro INI configuration
    # =======================
    [main]
    # Objects and their properties are defined here, 
    # Such as the securityManager, Realms and anything
    # else needed to build the SecurityManager
    
    [users]
    # The 'users' section is for simple deployments
    # when you only need a small number of statically-defined 
    # set of User accounts.
    
    [roles]
    # The 'roles' section is for simple deployments
    # when you only need a small number of statically-defined
    # roles.
    
    [urls]
    # The 'urls' section is used for url-based security
    # in web applications.  We'll discuss this section in the
    # Web documentation
    

    1) [main]

    配置sessionManager的实例和它的依赖。

    配置示例

    [main]
    sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
    
    myRealm = com.company.security.shiro.DatabaseRealm
    myRealm.connectionTimeout = 30000
    myRealm.username = jsmith
    myRealm.password = secret
    myRealm.credentialsMatcher = $sha256Matcher
    securityManager.sessionManager.globalSessionTimeout = 1800000
    

    定义一个对象

    [main]
    myRealm = com.company.shiro.realm.MyRealm
    ...
    

    简单的属性设置

    ...
    myRealm.connectionTimeout = 30000
    myRealm.username = jsmith
    ...
    

    配置信息将转入到对应的set方法中

    ...
    myRealm.setConnectionTimeout(30000);
    myRealm.setUsername("jsmith");
    ...
    

    参考值

    你可以使用$符号引用先前定义的一个对象的实例

    ...
    sha256Matcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher
    ...
    myRealm.credentialsMatcher = $sha256Matcher
    ...
    

    嵌套属性

    ...
    securityManager.sessionManager.globalSessionTimeout = 1800000
    ...
    

    将被注入到下面的程序中

    securityManager.getSessionManager().setGlobalSessionTimeout(1800000);
    

    引用其它的属性

    sessionListener1 = com.company.my.SessionListenerImplementation
    ...
    sessionListener2 = com.company.my.other.SessionListenerImplementation
    ...
    securityManager.sessionManager.sessionListeners = $sessionListener1, $sessionListener2
    

    以键值的配置方式

    object1 = com.company.some.Class
    object2 = com.company.another.Class
    ...
    anObject = some.class.with.a.Map.property
    
    anObject.mapProperty = key1:$object1, key2:$object2
    

    2) [users]

    在用户比较少的情况下这种配置信息是有效的

    [users]
    admin = secret
    lonestarr = vespa, goodguy, schwartz
    darkhelmet = ludicrousspeed, badguy, schwartz
    

    3) [roles]

    如果角色信息比较少的情况下可以使用这项配置

    [roles]
    # 'admin' role has all permissions, indicated by the wildcard '*'
    admin = *
    # The 'schwartz' role can do anything (*) with any lightsaber:
    schwartz = lightsaber:*
    # The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with
    # license plate 'eagle5' (instance specific id)
    goodguy = winnebago:drive:eagle5
    

    4) [urls]

    配置url等可访问的资源信息。


     

    作者:张锋
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。
    更多精彩文章可以观注
    微信公众号 soft张三丰

    微信交流群,添加群主微信,邀请入群
  • 相关阅读:
    软工试水日报-纯js原生简易动态表格 3/15
    软工试水日报-Echarts动态柱形图 3/14
    大二下学期第一次结对作业(第一阶段)
    大二下学期之第一次结对作业(第一阶段)
    大二下每周总结
    大二下学期之第一次结对作业(第一阶段)
    大二下学期第一次结对作业(第一阶段)
    大二下学期第一次结对作业(第一阶段)
    大二下学期每日总结之第一次个人作业(第三阶段)
    大二下学期每日总结之第一次个人作业(第三阶段)
  • 原文地址:https://www.cnblogs.com/skyme/p/2173842.html
Copyright © 2020-2023  润新知