Shiro、Realm

认识Realm
在Shiro里面考虑到以后可能面对于不同的用户数据的来源,所以为了统一这些来源的处理,准备了一个Realm接口,首先来观察org.apache.shiro.realm.Realm接口定义:

public interface Realm {

    /**
     * Returns the (application-unique) name assigned to this <code>Realm</code>. All realms configured for a single
     * application must have a unique name.
     *
     * @return the (application-unique) name assigned to this <code>Realm</code>.
     */
    String getName();

    /**
     * Returns <tt>true</tt> if this realm wishes to authenticate the Subject represented by the given
     * {@link org.apache.shiro.authc.AuthenticationToken AuthenticationToken} instance, <tt>false</tt> otherwise.
     *
     * <p>If this method returns <tt>false</tt>, it will not be called to authenticate the Subject represented by
     * the token - more specifically, a <tt>false</tt> return value means this Realm instance's
     * {@link #getAuthenticationInfo} method will not be invoked for that token.
     *
     * @param token the AuthenticationToken submitted for the authentication attempt
     * @return <tt>true</tt> if this realm can/will authenticate Subjects represented by specified token,
     *         <tt>false</tt> otherwise.
     */
    boolean supports(AuthenticationToken token);

    /**
     * Returns an account's authentication-specific information for the specified <tt>token</tt>,
     * or <tt>null</tt> if no account could be found based on the <tt>token</tt>.
     *
     * <p>This method effectively represents a login attempt for the corresponding user with the underlying EIS datasource.
     * Most implementations merely just need to lookup and return the account data only (as the method name implies)
     * and let Shiro do the rest, but implementations may of course perform eis specific login operations if so
     * desired.
     *
     * @param token the application-specific representation of an account principal and credentials.
     * @return the authentication information for the account associated with the specified <tt>token</tt>,
     *         or <tt>null</tt> if no account could be found.
     * @throws org.apache.shiro.authc.AuthenticationException
     *          if there is an error obtaining or constructing an AuthenticationInfo object based on the
     *          specified <tt>token</tt> or implementation-specifc login behavior fails.
     */
    AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;

}

固定信息Realm认证
如果要想使用Realm操作,那么必须要保证有一个具体的认证类实现了Realm接口。
1、 建立一个MyRealm子类,该类实现Realm接口;
· 认证信息:org.apache.shiro.authc.AuthenticationInfo,接口有两个方法:
|- 取得所有的身份信息:public PrincipalCollection getPrincipals();
|- 取得认证信息:public Object getCredentials()。
· 子类:org.apache.shiro.authc.SimpleAuthenticationInfo;
|- 构造方法:public SimpleAuthenticationInfo(Object principal, Object credentials, String realmName)。
· 所有用户的信息都保存在token里面:org.apache.shiro.authc.AuthenticationToken,此接口定义有如下两个方法: |- 身份数据:public Object getPrincipal();
|- 认证数据:public Object getCredentials()。
|- 此时返回的数据为char[]数组,不能直接转换为String;

实现自定义Realm

public class MyRealm implements Realm { 
    @Override 
    public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { 
        String username = (String) token.getPrincipal() ; 
        // 取得用户名
        // 在Shiro里面是利用字符数组实现了密码的传递,所以不能将其直接变为String 
        String password = new String((char[]) token.getCredentials()) ; 
        // 取得密码 
        // 此时直接使用一个固定的用户名和密码进行验证处理操作 
        if (!"admin".equals(username)) { 
            // 判断用户名是否存在 
            throw new UnknownAccountException("用户名不存在!") ; 
            } 
        if (!"hello".equals(password)) { 
            throw new IncorrectCredentialsException("密码输入错误!") ; 
            } 
        return new SimpleAuthenticationInfo(username,password,this.getName()) ; 
        } @Override public String getName() { 
            return "MyRealm";
            // 名字随便给一个,只要能唯一标记即可 
            } 
        @Override public boolean supports(AuthenticationToken token) {
            // 本次将在之前程序的基础之上继续使用UsernamePasswordToken完成信息的传递
            return token instanceof UsernamePasswordToken ; 
        }
    }
}

如果现在希望realm配置生效,则需要在配置文件里面进行相关定义。

修改shiro.ini文件

myRealm=cn.realm.MyRealm 

这个时候一定要注意,如果有多个Realm,则在“securityManager.realms”后面可以设置多个名称,中间使用“,”分割。

使用该Realm进行数据的认证处理:

public class TestLoginDemo {
    public static void main(String[] args) {
        // 取得Factory接口对象,主要的目的是通过配置文件加载文件之中的信息,这些信息暂时不能够成为认证信息
        Factory<org.apache.shiro.mgt.SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        // 取得里面所保存的所有的认证数据信息 org.apache.shiro.mgt.SecurityManager
        securityManager = factory.getInstance(); //
        // 利用一个专门的认证操作的处理类,实现认证处理的具体的实现
        SecurityUtils.setSecurityManager(securityManager); //
        // 获取进行用户名和密码认证的接口对象
        Subject subject = SecurityUtils.getSubject();
        // 定义了一个Token,里面保存要登录的用户名和密码信息
        UsernamePasswordToken token = new UsernamePasswordToken("admin", "hello");
        // 实现用户登录处理
        subject.login(token);
        System.out.println(subject.getPrincipal()); 
        // 取得用户名
    }
    }

基于数据库的验证处理

需要建立一张用户表:member;

表中需要拥有以下字段:
mid,password,name,locked(锁定标记)
处理操作所有的核心配置都不是通过程序完成的,都是通过配置文件完成的,可以直接使用MySQL 提供好的

数据库连接池配置。

修改shiro.ini 的文件

[main]
dataSource=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
    #定义数据库的连接主机名称 dataSource.serverName=127.0.0.1
    #定义要使用的数据库的名字 dataSource.databaseName=shirodb
    #定义数据库的连接账户 dataSource.user=root
    #定义数据库的连接的密码 dataSource.password=mysqladmin
    #定义本次要基于JDBC实现的Realm的认证的配置类 jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
    #配置本次的JDBC连接所使用的数据源,$表示引用配置 
    jdbcRealm.dataSource=$dataSource
    #定义所需要的查询语句 jdbcRealm.authenticationQuery=SELECT password FROM member WHERE mid=? 
    # 配置安全管理器所使用的
    Realm securityManager.realms=$jdbcRealm

此时继续使用之前的程序进行执行,这个时候将利用JDBC实现用户的登录检测操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值