Shiro 的身份认证-Realm

1. Realm是什么

Realm域 保存着安全数据(如用户,角色,权限)。

SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作

2. 自定义Realm

package cn.javass.hello;

import java.util.HashSet;
import java.util.Set;

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.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

/**
 * 自定义Realm
 * 
 * @author Administrator
 *
 */
public class MyRealm extends AuthorizingRealm {

    /*
     * 授权信息
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        String username = (String) getAvailablePrincipal(principals);
        // 通过用户名去获得用户的所有资源,并把资源存入info中

        // 1.根据用户名去数据库查询它有哪些权限,并放入info
        Set<String> permission = new HashSet<String>();
        permission.add("p1");
        permission.add("p2");
        info.setStringPermissions(permission);
        // 2.根据用户名去数据库查询它有哪些角色,并放入info
        Set<String> role = new HashSet<String>();
        role.add("r1");
        role.add("r2");
        info.setRoles(role);
        // 返回授权信息
        return info;

    }

    /*
     * 认证信息
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // token中储存着输入的用户名和密码
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();
        String password = String.valueOf(upToken.getPassword());

        // 通常是与数据库中用户名和密码进行对比,这里就省略了
        // 比对成功则返回info,比对失败则抛出对应信息的异常 AuthenticationException
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password.toCharArray(), getName());
        // 返回认知信息
        return info;
    }

}

3. 身份认证时 多个Realm的配置和处理

3.1. 在程序中自定义两个域
MyRealm1
MyRealm2抛出异常
当有自定义两个Realm域时,实际上有三个域,还有一个默认的iniRealm

if (username.equals("javass")) {
            throw new AuthenticationException("MyRealm2 认证失败");
}

3.2. 在shiro.ini配置文件中配置认证器 认证策略 认证域

定义认证器 认证域 认证策略 ,然后把认证域和认证策略复制给认证器

[main]
#定义两个域
myRealm1 = cn.javass.hello.MyRealm1
myRealm2 = cn.javass.hello.MyRealm2

authenticator=org.apache.shiro.authc.pam.ModularRealmAuthenticator
authcStrategy=org.apache.shiro.authc.pam.AllSuccessfulStrategy
authenticator.authenticationStrategy = $authcStrategy
authenticator.realms = $myRealm1, $myRealm2

securityManager.authenticator = $authenticator

4. 多个Realm时的认证策略AuthenticationStrategy

4.1. 当有多个认证域时,默认的认证策略有三个。默认AtLeastOneSuccessfulStrategy

AtLeastOneSuccessfulStrategy:如有一个或多个Reaml验证成功,则整体尝试成功。如果没有一个验证成功,则整体验证失败

FirstSuccessfulStrategy:只有第一个成功验证的Realm返回的信息将被使用。如果没有一个验证成功,则整体验证失败

AllSuccessfulStrategy:所有配置的Realm必须验证成功,整体验证才成功。如果没有一个验证成功,则整体验证失败

4.2 自定义认证策略

package cn.javass.hello;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.pam.AbstractAuthenticationStrategy;
import org.apache.shiro.realm.Realm;

/**
 * 自定义认证策略
 *
 * 只有MyRealm2域认证通过,才可以
 *
 */
public class MyAuthenticationStrategy extends AbstractAuthenticationStrategy {

    public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo singleRealmInfo,
            AuthenticationInfo aggregateInfo, Throwable t) throws AuthenticationException {
            //ini文件中域的名字MyRealm2
        if (realm.getName().equals("MyRealm2")) {
            if (singleRealmInfo == null || singleRealmInfo.getPrincipals() == null) {
                throw new AuthenticationException("主站认证未通过");
            }
        }
        return super.afterAttempt(realm, token, singleRealmInfo, aggregateInfo, t);
    }
}

4.3 给认证器 设置自定义的认证策略

authcStrategy=cn.javass.hello.MyAuthenticationStrategy

5. 多个Realm的认证顺序

默认的iniRealm是第一个
5.1 显示指定 按照指定的顺序

authenticator.realms = $myRealm1, $myRealm2

5.2 没有执行,按照自定义Realm的定义顺序

myRealm1 = cn.javass.hello.MyRealm1
myRealm2 = cn.javass.hello.MyRealm2

不同的域里存储着不同的身份
如域1: 用户名/密码
域2:电话号码/密码
域3:邮箱/密码

域返回的是什么

posted on 2017-09-27 15:18  dreamstar  阅读(91)  评论(0编辑  收藏  举报