shiro中的认证

一、认证

身份认证,就是判断一个用户是否为合法用户的处理过程。最常用的简单身份认证方式是系统通过核对用户输入的用户名和口令,看其是否与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确。

二、 shiro中认证的关键对象

1、subject:主体

访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体;

2、Principal:身份信息

是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)。

3、credential:凭证信息

是只有主体自己知道的安全信息,如密码、证书等。

三、认证流程

在这里插入图片描述

四、认证的开发

1、创建maven项目并引入依赖

<dependency>
  <groupId>org.apache.shiro</groupId>
  <artifactId>shiro-core</artifactId>
  <version>1.5.3</version>
</dependency>

2、引入shiro配置文件并加入如下配置

[users]
zhangsan=123
lisi=456
czy=789

在这里插入图片描述

3、开发认证代码

// 测试shiro的身份认证
public class TestAuthenticator {
    public static void main(String[] args) {
        // 1.创建shiro的安全管理器
        DefaultSecurityManager securityManager = new DefaultSecurityManager();

        // 2.给安全管理器设置realm
        securityManager.setRealm(new IniRealm("classpath:shiro.ini"));

        // 3.SecurityUtils 给全局安全工具类设置安全管理器
        SecurityUtils.setSecurityManager(securityManager);

        // 4.使用SecurityUtils获取用户的身份信息subject主体
        Subject subject = SecurityUtils.getSubject();

        // 5.创建令牌
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan1", "1233");

        try {
            System.out.println("身份认证:" + subject.isAuthenticated());
            // 6.进行身份认证
            subject.login(token);
            System.out.println("身份认证:" + subject.isAuthenticated());
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用户名不存在!");
        }catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            System.out.println("密码错误!");
        }
    }
}

五、自定义Realm

上边的程序使用的是Shiro自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义Realm。

1、shiro提供的Realm

在这里插入图片描述

2、根据认证源码认证使用的是SimpleAccountRealm

在这里插入图片描述
SimpleAccountRealm的部分源码中有两个方法一个是认证 一个是授权

public class SimpleAccountRealm extends AuthorizingRealm {
//......
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken upToken = (UsernamePasswordToken)token;
        SimpleAccount account = this.getUser(upToken.getUsername());
        if (account != null) {
            if (account.isLocked()) {
                throw new LockedAccountException("Account [" + account + "] is locked.");
            }

            if (account.isCredentialsExpired()) {
                String msg = "The credentials for account [" + account + "] are expired";
                throw new ExpiredCredentialsException(msg);
            }
        }

        return account;
    }

    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = this.getUsername(principals);
        this.USERS_LOCK.readLock().lock();

        AuthorizationInfo var3;
        try {
            var3 = (AuthorizationInfo)this.users.get(username);
        } finally {
            this.USERS_LOCK.readLock().unlock();
        }

        return var3;
    }
}

3、自定义Realm

/**
 * 自定义realm
 */
public class CustomRealm extends AuthorizingRealm {
    // 授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    // 认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 通过token获取用户输入的信息
        String principal = (String) token.getPrincipal();
        System.out.println(principal);
        // 通过用户名来查询数据库中的信息 jdbc jpa mybatis
        if ("zhangsan".equals(principal)){
            // 参数1:返回数据库中正确的用户名   参数2:返回数据库正确的密码     参数3:获取当前realm的名字
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal, "123", this.getName());
            return simpleAuthenticationInfo;
        }
        return null;
    }
}

4、使用自定义Realm认证

/**
 * 测试使用自定义的realm来实现shiro身份认证
 */
public class TestCustomRealmAuthenticator {
    public static void main(String[] args) {
        // 1.创建安全管理器
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        // 2.设置自定义的realm(相当于从数据库中读取的)
        defaultSecurityManager.setRealm(new CustomRealm());
        // 3.使用安全工具类设置管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        // 4.使用安全工具类获取subject主体
        Subject subject = SecurityUtils.getSubject();
        // 5.使用用户名和密码创建一个令牌token(相当于用户自己输入的用户名和密码信息)
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123123");

        try {
            // 6.使用subject进行登录
            subject.login(token);
            System.out.println(subject.isAuthenticated());
        } catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("用户名错误!");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误!");
        }
    }
}

六、使用MD5和Salt

实际应用是将盐和散列后的值存在数据库中,Realm从数据库取出盐和加密后的值由shiro完成密码校验。
MD5加密算法的特点:算法不可逆(只能由明文加密得到密文,反之则不行);如果内容相同,无论进行多少次MD5加密其结果始终保持一致。
MD5算法的应用:加密; 签名

1、自定义md5+salt的Realm

/**
 * 自定义一个带有MD5 + salt + 散列的realm
 */
public class CustomMD5Realm extends AuthorizingRealm {


    // 授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    // 身份认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 从token中获取身份信息
        String principal = (String) token.getPrincipal();
        // 根据用户名到数据库中进行查找
        if ("zhangsan".equals(principal)){
            return new SimpleAuthenticationInfo(principal,
                    "4090ec9c2cfd8341455ae0e6c80ae696",
                    ByteSource.Util.bytes("QPX@!"),
                    this.getName());
        }
        return null;
    }

}

2、使用md5 + salt 认证

**
 * 测试MD5加密算法身份认证
 */
public class TestCustomMD5RealmAuthenticator {
    public static void main(String[] args) {
        // 1.创建安全管理器
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        // 2.设置自定义realm
        CustomMD5Realm customMD5Realm = new CustomMD5Realm();

        // 使用hash凭证匹配器
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        // 使用的加密算法
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        // 设置哈希散列的次数
        hashedCredentialsMatcher.setHashIterations(1024);

        customMD5Realm.setCredentialsMatcher(hashedCredentialsMatcher);

        defaultSecurityManager.setRealm(customMD5Realm);
        // 3.注入安全工具类
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        // 4.获取subject主体
        Subject subject = SecurityUtils.getSubject();
        // 5.获取token
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");

        try {
            // 6.登录认证
            subject.login(token);
            System.out.println("登录成功");
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("用户名错误!");
        }catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            System.out.println("密码错误!");
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值