二、Shiro 认证开发

I、java开发

环境准备

<dependencies>     
    <dependency>         
        <groupId>junit</groupId>         
        <artifactId>junit</artifactId>         
        <version>4.9</version>     
    </dependency>     
    <dependency>         
        <groupId>commons-logging</groupId>         
        <artifactId>commons-logging</artifactId>         
        <version>1.1.3</version>     
    </dependency>     
    <dependency>         
        <groupId>org.apache.shiro</groupId>        
        <artifactId>shiro-core</artifactId>         
        <version>1.2.2</version>     
    </dependency> 
</dependencies> 

shiro配置文件: shiro.ini

[users]
zhang3=123123
li4=123456

测试

//测试认证
public class TestAuthor {
    /**
     * 认证
     * 安全管理器
     * 获取主题
     * token
     *
     */
    public static void main(String[] args) {
        //通过安全管理器工厂
        IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //获得安全管理器工厂
        SecurityManager securityManager = iniSecurityManagerFactory.getInstance();
        //将安全管理器交给安全工具类
        SecurityUtils.setSecurityManager(securityManager);

        //主体对象
        Subject subject = SecurityUtils.getSubject();
        //构建token
        UsernamePasswordToken token = new UsernamePasswordToken("zhang3", "123123");
        try {
            subject.login(token);
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }
        //验证是否通过
        System.out.println(subject.isAuthenticated());
    }

}

异常

IncorrectCredentialsException:密码输入错误

UnknownAccountException:账户对比失败

DisabledAccountException:帐号被禁用

LockedAccountException:帐号被锁定

ExcessiveAttemptsException:登录失败次数过多

ExpiredCredentialsException:凭证过期

底层认证思路

public class MyRealm extends AuthenticatingRealm{
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    /**
    * 假装查询数据库
    *
    *
    */
		//获取用户名
        String principal = (String) authenticationToken.getPrincipal();
        if (principal.equals("zhang3")){
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo("zhang3", "123123", this.getName());
            return simpleAuthenticationInfo;

        }
        return null;
	}	

}

II、Shiro认证过程

①. 应用程序代码调用 Subject.login 方法,传递创建好的包含终端用户的 Principals(身份)和 Credentials(凭证)的 AuthenticationToken 实例

②. Subject 实例: 通常为 DelegatingSubject(或子类)委托应用程序的 SecurityManager 通过调用securityManager.login(token) 开始真正的验证。

③. SubjectManager 接收 token,调用内部的 Authenticator 实例调用 authenticator.authenticate(token).Authenticator 通常是一个 ModularRealmAuthenticator 实例, 支持在身份验证中协调一个或多个Realm 实例

④. 如果应用程序中配置了一个以上的 Realm, ModularRealmAuthenticator 实例将利用配置好的AuthenticationStrategy 来启动 Multi-Realm 认证尝试. 在Realms 被身份验证调用之前, 期间和以后,AuthenticationStrategy 被调用使其能够对每个Realm 的结果作出反应.

⑤. 每个配置的 Realm 用来帮助看它是否支持提交的 AuthenticationToken. 如果支持, 那么支持 Realm 的 getAuthenticationInfo 方法将会伴随着提交的 token 被调用. getAuthenticationInfo 方法有效地代表一个特定 Realm 的单一的身份验证尝试

III、Shiro的加密认证

测试加密的结果,元数据为12313,盐为1345,散列1024次=b8cc2120cdf1554cf35603e08f7f5524

public class TestMD5Hash {
    public static void main(String[] args) {
        //param 元数据 盐 散列
        Md5Hash md5Hash = new Md5Hash("123123","1345",1024);
        String s = md5Hash.toHex();
        System.out.println(s);
    }
}

自定义规则

public class MyRealm2 extends AuthenticatingRealm {
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String principal = (String) authenticationToken.getPrincipal();
        if (principal.equals("zhang3")){
            return new SimpleAuthenticationInfo("zhang3","b8cc2120cdf1554cf35603e08f7f5524", ByteSource.Util.bytes("1345"),this.getName());
        }
        return null;
    }
}

配置文件定义规则和加密规则

[main]
# 声明凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher

# 声明realm
realm2=com.baizhi.shiro2.MyRealm2
securityManager.realms=$realm2

# 告知realm使用HashedCredentialsMatcher 为凭证匹配器
realm2.credentialsMatcher=$credentialsMatcher

# 告知安全管理器使用自定义
securityManager.realms=$realm2

# 告知Shiro算法的名称
credentialsMatcher.hashAlgorithmName=md5
credentialsMatcher.hashIterations=1024

public class TestAuthen2 {
    public static void main(String[] args) {
        IniSecurityManagerFactory securityManagerFactory = new IniSecurityManagerFactory("classpath:shiro1.ini");
        SecurityManager securityManager = securityManagerFactory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken("zhang3", "123123");

        try {
            subject.login(token);
        } catch (UnknownAccountException e) {
            System.out.println("用户名错误");

        } catch (IncorrectCredentialsException e){
            System.out.println("密码错误");
        }
        boolean authenticated = subject.isAuthenticated();
        System.out.println(authenticated);

    }


}
posted @ 2019-01-04 11:23  罗小扇  阅读(66)  评论(0)    收藏  举报