Shiro学习_02(认证)

Shiro身份验证

  • 认证: 判断一个用户是否为合法用户的处理过程。即提供用户名和密码,检验是否与数据库存储的用户名密码一致。

Shrio中认证的管家对象

  • Subject:主体

访问系统的用户

  • Principal:身份信息

身份,即主体的标识属性,可以是任何东西,如用户名、邮箱等,唯一即可。
一个主体可以有多个principals,但只有一个Primary principals,一般是用户名/密码/手机号

  • Credential:凭证信息

证明 / 凭证,即只有主体知道的安全值,如密码 / 数字证书等。

认证流程

使用加密认证(MD5+Salt+Hash)

MD5加密

package com.shiro.util;

import org.apache.shiro.crypto.hash.Md5Hash;

import java.util.UUID;

public class TestShiroMD5 {
    public static void main(String[] args) {
        // 可以使用uuid作为盐值
        String uuid = UUID.randomUUID().toString().replace("-", "");
        System.out.println("UUID: "+uuid);
        // 使用md5 + salt + hash散列(参数代表要散列多少次,一般是 1024或2048)
        Md5Hash md5Hash2 = new Md5Hash("123456", uuid, 1024);
        System.out.println(md5Hash2.toHex());
    }
}
  • 输出

UUID: 3e451cd1bce14b5e86588a13559c83d6
094aa06418bda3cbb3cb61c875e6c5a9

自定义加密的Realm

package com.shiro.realm;

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


/**
 * 使用自定义realm 加入md5 + salt +hash
 */
public class CustomerMd5Realm extends AuthorizingRealm {

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

    /**
     * 认证
     *
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 获取token中的用户名和密码
        String principal = (String) token.getPrincipal();
        String credentials = new String((char[]) token.getCredentials());

        // 模拟数据库查询到的信息
        String username = "shiro";
        // 密码使用MD5生成加密后的密码”123456“
        String password = "094aa06418bda3cbb3cb61c875e6c5a9";
        // 使用uuid生成的值作为盐值
        String salt = "3e451cd1bce14b5e86588a13559c83d6";

        // 根据用户名查询数据库
        if (username.equals(principal)) {
            /**
             * 依次传入:账号信息、加密后的密码、密码加密的盐值、当前realm对象的name
             */
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal
                    , password
                    , ByteSource.Util.bytes(salt)
                    , this.getName());

            return simpleAuthenticationInfo;
        }
        return null;
    }
}

使用加密Realm认证

package com.shiro.test;

import com.shiro.realm.CustomerMd5Realm;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;

@Slf4j
public class TestCustomerMd5RealmAuthenicator {

    public static void main(String[] args) {
        // 1.创建安全管理员
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        // 2.注入realm
        CustomerMd5Realm realm = new CustomerMd5Realm();
        // 3.设置realm使用hash凭证匹配器
        HashedCredentialsMatcher credentialsMathcher = new HashedCredentialsMatcher();
        // 设置使用的算法
        credentialsMathcher.setHashAlgorithmName("md5");
        // 设置散列次数
        credentialsMathcher.setHashIterations(1024);

        realm.setCredentialsMatcher(credentialsMathcher);
        defaultSecurityManager.setRealm(realm);

        // 4.将安全管理器注入安全工具
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        // 5.通过安全工具类获取subject
        Subject subject = SecurityUtils.getSubject();
        // 6.认证
        UsernamePasswordToken token = new UsernamePasswordToken("shiro", "123456");

        try {
            subject.login(token);
            log.info("登录成功");
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            log.error("用户名错误");
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            log.error("密码错误");
        }
    }
}

未加密

自定义Realm

package com.shiro.realm;

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

/**
 * 自定义Realm
 */
public class CustomerRealm extends AuthorizingRealm {

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

    /**
     * 认证
     *
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // 从token中获取用户名
        String principal = (String) token.getPrincipal(); //得到用户名
        String credentials = new String((char[])token.getCredentials()); //得到密码
        System.out.println(principal);
        System.out.println(credentials);

        // 在实际开发中,用户身份信息是从数据库中查询的
        // 假设从数据库中获取了用户名和密码
        String username = "shiro";
        String password = "123456";

        if (username.equals(principal)) {
            /**
             * principal: 数据库的用户名
             * password: 数据库的密码
             * this.getName(): 提供当前realm的名字
             */
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal
                    , password
                    , this.getName());

            return simpleAuthenticationInfo;
        }
        return null;
    }
}

使用未加密Realm认证

package com.shiro.test;

import com.shiro.realm.CustomerRealm;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;

/**
 * 测试自定义的Realm
 */
@Slf4j
public class TestAuthenticatorCusttomerRealm {

    public static void main(String[] args) {
        // 1.创建安全管理对象securityManager
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        // 2.给安全管理器设置realm(设置为自定义realm获取认证数据)
        defaultSecurityManager.setRealm(new CustomerRealm());
        // 3.给安装工具类中设置默认安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        // 4.获取主体对象subject
        Subject subject = SecurityUtils.getSubject();
        // 5.创建token令牌
        UsernamePasswordToken token = new UsernamePasswordToken("shiro", "123456");

        try {
            // 用户登录
            subject.login(token);
            log.info("登陆成功");
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            log.error("用户名或密码错误");
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hanlin-hl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值