• shiro(3)shiro核心


    身份认证

    身份认证分三个步骤

    1)提交主题和凭据

    2)进行身份认证

    3)判断是通过,重新提交还是不通过

    验证顺序

    1)调用subject的login方法,提交主体和凭据。

    2)得到对应操作的Security Manager

    3)通过Sceurity Manager得到对应的Autherticator实例

    4)根据配置策略查找对应的桥信息

    5)通过桥信息到对应的配置处理进行身份验证

    验证器

    如果你想配置一个自定义的验证器

    可以在配置文件中使用

    [main]
    ...
    authenticator = com.foo.bar.CustomAuthenticator
    
    securityManager.authenticator = $authenticator
    

    配置策略信息

    AtLeastOneSuccessfulStrategy 如果一个验证成功,则验证结果为成功

    FirstSuccessfulStrategy         只有第一个成功,才算成功

    AllSuccessfulStrategy            所有的都必须成功

    对应的在配置文件中的策略使用如下

    shiro.ini
    
    [main]
    ...
    authcStrategy = org.apache.shiro.authc.pam.FirstSuccessfulStrategy
    
    securityManager.authenticator.authenticationStrategy = $authcStrategy
    
    ...
    
    

    执行顺序

    1)隐式顺序

    blahRealm = com.company.blah.Realm
    ...
    fooRealm = com.company.foo.Realm
    ...
    barRealm = com.company.another.Realm
    

    按上下顺序执行

    2)指定顺序

    blahRealm = com.company.blah.Realm
    ...
    fooRealm = com.company.foo.Realm
    ...
    barRealm = com.company.another.Realm
    
    securityManager.realms = $fooRealm, $barRealm, $blahRealm
    ...
    

    按指定的顺序执行

    授权

    控制谁有权限访问应用程序

    授权的几个要素:权限,角色和用户。

    三种权限的判断方式

    1)编程

    角色判断

    Subject currentUser = SecurityUtils.getSubject();
    
    if (currentUser.hasRole("administrator")) {
        //show the admin button
    } else {
        //don't show the button?  Grey it out?
    }
    

    hasRole(String roleName)                            主题是否已分配给指定的角色

    hasRoles(List<String> roleNames)                是否包含指定的角色

    hasAllRoles(Collection<String> roleNames)   是否包含指定的所有角色

    角色断言

    Subject currentUser = SecurityUtils.getSubject();
    
    //guarantee that the current user is a bank teller and
    //therefore allowed to open the account:
    currentUser.checkRole("bankTeller");
    openBankAccount();
    

    checkRole(String roleName)                       断言是否是指定角色

    checkRoles(Collection<String> roleNames)  断言是否包含以下角色

    checkRoles(String... roleNames)                断言是否包含所有角色

    如果判断指定用户是否有权限访问指定名称的打印机

    那么就会用到下列几个方法

    Permission printPermission = new PrinterPermission("laserjet4400n", "print");
    
    Subject currentUser = SecurityUtils.getSubject();
    
    if (currentUser.isPermitted(printPermission)) {
        //show the Print button
    } else {
        //don't show the button?  Grey it out?
    }
    

    isPermitted(Permission p) 判断主题是否允许执行一个动作

    isPermitted(List<Permission> perms) 是否允许执行一组动作

    isPermittedAll(Collection<Permission> perms) 是否允许执行所有动作

    基于字符串的权限检查

    Subject currentUser = SecurityUtils.getSubject();
    
    if (currentUser.isPermitted("printer:print:laserjet4400n")) {
        //show the Print button
    } else {
        //don't show the button?  Grey it out?
    }
    

    也可以如下使用

    Subject currentUser = SecurityUtils.getSubject();
    
    Permission p = new WildcardPermission("printer:print:laserjet4400n");
    
    if (currentUser.isPermitted(p) {
        //show the Print button
    } else {
        //don't show the button?  Grey it out?
    }
    

    权限断言类似于角色断言。

    2)annocation方式

    The RequiresAuthentication annotation

    @RequiresAuthentication
    public void updateAccount(Account userAccount) {
        //this method will only be invoked by a 
        //Subject that is guaranteed authenticated
        ...
    }
    

    等同于下述代码

    public void updateAccount(Account userAccount) {
        if (!SecurityUtils.getSubject().isAuthenticated()) {
            throw new AuthorizationException(...);
        }
        
        //Subject is guaranteed authenticated here
        ...
    }
    

    The RequiresGuest annotation

    @RequiresGuest
    public void signUp(User newUser) {
        //this method will only be invoked by a 
        //Subject that is unknown/anonymous
        ...
    }
    

    等同于

    public void signUp(User newUser) {
        Subject currentUser = SecurityUtils.getSubject();
        PrincipalCollection principals = currentUser.getPrincipals();
        if (principals != null && !principals.isEmpty()) {
            //known identity - not a guest:
            throw new AuthorizationException(...);
        }
        
        //Subject is guaranteed to be a 'guest' here
        ...
    }
    

    The RequiresPermissions annotation

    @RequiresPermissions("account:create")
    public void createAccount(Account account) {
        //this method will only be invoked by a Subject
        //that is permitted to create an account
        ...
    }
    

    等同于

    public void createAccount(Account account) {
        Subject currentUser = SecurityUtils.getSubject();
        if (!subject.isPermitted("account:create")) {
            throw new AuthorizationException(...);
        }
        
        //Subject is guaranteed to be permitted here
        ...
    }
    

    The RequiresRoles permission

    @RequiresRoles("administrator")
    public void deleteUser(User user) {
        //this method will only be invoked by an administrator
        ...
    }
    

    等同于

    public void deleteUser(User user) {
        Subject currentUser = SecurityUtils.getSubject();
        if (!subject.hasRole("administrator")) {
            throw new AuthorizationException(...);
        }
        
        //Subject is guaranteed to be an 'administrator' here
        ...
    }
    

    The RequiresUser annotation

    @RequiresUser
    public void updateAccount(Account account) {
        //this method will only be invoked by a 'user'
        //i.e. a Subject with a known identity
        ...
    }
    

    等同于

    public void updateAccount(Account account) {
        Subject currentUser = SecurityUtils.getSubject();
        PrincipalCollection principals = currentUser.getPrincipals();
        if (principals == null || principals.isEmpty()) {
            //no identity - they're anonymous, not allowed:
            throw new AuthorizationException(...);
        }
        
        //Subject is guaranteed to have a known identity here
        ...
    }
    

    授权顺序

    1)应用程序调用主题,判断hasRole,isPermitted得到角色或者用户权限的列表。

    2)组成对应的授权方法

    3)协调如何授权

    4)通过桥进行各种方式的授权

    web应用

    配置web.xml

    <listener>
        <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
    </listener>
    
    ...
    
    <filter>
        <filter-name>ShiroFilter</filter-name>
        <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>ShiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

    如果你愿意你可以自定义一个web应用

    <context-param>
        <param-name>shiroEnvironmentClass</param-name>
        <param-value>com.foo.bar.shiro.MyWebEnvironment</param-value>
    </context-param>
    

    如果你想改变shiro.ini的位置,那么你可以指定

    <context-param>
        <param-name>shiroConfigLocations</param-name>
        <param-value>YOUR_RESOURCE_LOCATION_HERE</param-value>
    </context-param>
    

    shiro.ini中的[urls]配置

    例如:

    ...
    [urls]
    
    /index.html = anon
    /user/create = anon
    /user/** = authc
    /admin/** = authc, roles[administrator]
    /rest/** = authc, rest
    /remoting/rpc/** = authc, perms["remote:invoke"]
    

    假如你有如下设置

    /account/** = ssl, authc
    

    /account下的任何应用程序都将触动ssl和authc链


     


     

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

    微信交流群,添加群主微信,邀请入群
  • 相关阅读:
    codeforces-1144 (div3)
    codeforces-1142 (div1)
    codeforces-1131 (div2)
    codeforces-1132 (div2)
    [HAOI2006]均分数据
    Ellipsoid
    [JSOI2004]平衡点 / 吊打XXX
    CF208E Blood Cousins
    CF570D Tree Requests
    CF600E Lomsat gelral
  • 原文地址:https://www.cnblogs.com/skyme/p/2173979.html
Copyright © 2020-2023  润新知