1.shiro认证

Shiro

代码地址gitee

1 认证

1.1 使用ini配置文件来实现认证

shiro实现简单的认证,用户名的账号和密码放在了根目录下的shiro.ini文件中

[users]
zhangsan=123123
lisi=123123

在设置securityManager的Realm的时候,选择new一个IniRealm,传入shiro.ini的路径

// 创建安全管理器对象
DefaultSecurityManager securityManager = new DefaultSecurityManager();
// 给安全管理器设置realm
securityManager.setRealm(new IniRealm("classpath:shiro.ini"));

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

// 关键对象subject主体
Subject subject = SecurityUtils.getSubject();

// 创建令牌
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123123");

// 用户认证
try {
  subject.login(token);
} catch (UnknownAccountException e) {
  e.printStackTrace();
  System.out.println("账号不存在");
} catch (IncorrectCredentialsException e) {
  e.printStackTrace();
  System.out.println("密码错误");
}

1.2 使用自己定义的Realm来实现认证

我们自定义的Realm需要继承AuthorizingRealm,重写doGetAuthorizationInfo()授权方法和doGetAuthenticationInfo()认证方法
点击这里查看源码追溯的文章
通过追溯源码可以得到如下依赖图:

  • AuthenticatingRealm 认证的Realm抽象类
  • AuthorizingRealm 授权的Realm抽象类
  • 用户名比较是在SimpleAccountRealm中的doGetAuthenticationInfo 完成用户名校验
  • 密码是在AuthenticatingRealm中的assertCredentialsMatch完成校验
  • 通过图可以看出,继承AuthorizingRealm就可以重写认证AuthenticatingRealm和授权AuthorizingRealm两个抽象类的方法

在这里插入图片描述

自定义Realm类

public class CustomerRealm extends AuthorizingRealm {

    // 授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }
  
    // 认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        // token中获取用户名
        String principal = (String) token.getPrincipal();
        System.out.println("principal = " + principal);

        // 根据用户名获取数据,例如 queryUserByUsername(principal);
      	// 这里模拟数据库中获取数据
        if ("zhangsan".equals(principal)) {
            /**
             * 参数1: 返回数据库中正确的用户名
             * 参数2: 密码
             * 参数3: 提供当前的realm的名字,直接调用父类的getName()方法
             */
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo("zhangsan", "123123", this.getName());
            return simpleAuthenticationInfo;
        }
        return null;
    }
}

下述测试自定义Realm类的时候,只是将new IniRealm()改成new自己定义的Realm。后期和数据中的账号密码作比较是在自己定义的Realm中进行的。

// 创建securityManager
DefaultSecurityManager securityManager = new DefaultSecurityManager();

// 设置自定义Realm
securityManager.setRealm(new CustomerRealm());

// 将安全工具类设置为安全工具类
SecurityUtils.setSecurityManager(securityManager);

// 通过安全工具类获取Object
Subject subject = SecurityUtils.getSubject();

// 创建token
UsernamePasswordToken token = new UsernamePasswordToken("zhangsan","123123");

// 登录
try {
  subject.login(token);
} catch (AuthenticationException e) {
  e.printStackTrace();
}

1.3 自定义Realm的md5加密加盐比较

md5加密 是不可逆的,同一数据在进行md5加密后得到的加密字符串相同。

自定义MD5Realm类

public class CustomerMD5Realm extends AuthorizingRealm {
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        // 获取身份信息
        String principal = (String) token.getPrincipal();

        // 根据用户名查询数据库
        if ("zhangsan".equals(principal)) {

            /**
             * 参数一: 数据库中的密码
             * 参数二:md5+salt之后的密码
             * 参数三:盐值
             * 参数四:当前realm的名称
             */
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
                    "zhangsan",
                    "f997c74487a098c9477da3a0c10944a5",
                    ByteSource.Util.bytes("s0*5ps"),
                    getName());
            return info;
        }

        return null;
    }
}

md5加密测试类

相比之前不同的是,我们在new Realm之后,对Realm进行设置加密算法和迭代次数。迭代次数不同得到的MD5加密字符串也不同。

扩展:

​ 这里的盐值我们后期可以通过字符串生成工具来随机生成字符串,并将其存入数据库中,在进行登录的时候,用相同的加密原则来进行判断。例如,我们注册的时候是将盐值加载密码后面再进行加密,我们登录的时候就要将数据库中的盐值加在密码后面。

public class TestCustomerMD5RealmAuthenticator {
    public static void main(String[] args) {
        // 创建安全管理器
        DefaultSecurityManager securityManager = new DefaultSecurityManager();
        // 注入realm
        CustomerMD5Realm realm = new CustomerMD5Realm();
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        // 注册算法
        hashedCredentialsMatcher.setHashAlgorithmName("md5");
        // 散列次数
//        hashedCredentialsMatcher.setHashIterations(1024);
        realm.setCredentialsMatcher(hashedCredentialsMatcher);

        // 为securityManager设置Realm
        securityManager.setRealm(realm);

        // 设置securityManager
        SecurityUtils.setSecurityManager(securityManager);

        // 获取subject对象
        Subject subject = SecurityUtils.getSubject();

        // 创建token
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");

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

    }
}

下一章:shiro的授权

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
图像识别技术在病虫害检测中的应用是一个快速发展的领域,它结合了计算机视觉和机器学习算法来自动识别和分类植物上的病虫害。以下是这一技术的一些关键步骤和组成部分: 1. **数据收集**:首先需要收集大量的植物图像数据,这些数据包括健康植物的图像以及受不同病虫害影响的植物图像。 2. **图像预处理**:对收集到的图像进行处理,以提高后续分析的准确性。这可能包括调整亮度、对比度、去噪、裁剪、缩放等。 3. **特征提取**:从图像中提取有助于识别病虫害的特征。这些特征可能包括颜色、纹理、形状、边缘等。 4. **模型训练**:使用机器学习算法(如支持向量机、随机森林、卷积神经网络等)来训练模型。训练过程中,算法会学习如何根据提取的特征来识别不同的病虫害。 5. **模型验证和测试**:在独立的测试集上验证模型的性能,以确保其准确性和泛化能力。 6. **部署和应用**:将训练好的模型部署到实际的病虫害检测系统中,可以是移动应用、网页服务或集成到智能农业设备中。 7. **实时监测**:在实际应用中,系统可以实时接收植物图像,并快速给出病虫害的检测结果。 8. **持续学习**:随着时间的推移,系统可以不断学习新的病虫害样本,以提高其识别能力。 9. **用户界面**:为了方便用户使用,通常会有一个用户友好的界面,显示检测结果,并提供进一步的指导或建议。 这项技术的优势在于它可以快速、准确地识别出病虫害,甚至在早期阶段就能发现问题,从而及时采取措施。此外,它还可以减少对化学农药的依赖,支持可持续农业发展。随着技术的不断进步,图像识别在病虫害检测中的应用将越来越广泛。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值