Shiro学习(三)之MD5+随机盐salt+Hash散列认证

本文介绍了Shiro中结合MD5和随机盐进行散列认证的过程。MD5算法因其不可逆性常用于加密和签名,防止穷举攻击。在认证流程中,先对密码进行加盐处理,确保即使使用相同的MD5,生成的散列值也不一样,增强了安全性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MD5:

  1. 加密算法不可逆(只能根据明文生成密文;如果内容相同,不论执行多少次md5生成结果始终一致),通常和随机盐配合使用

  2. 一般用来加密或签名

  3. 签名:也称为校验和,就是用来判断两个内容是否一致
    eg: tomcat.zip tomcat.md5. fdfd… 看是否下载完整,就可以点击tomcat.md5. 看生成的签名和tomcat生成的是否一致
    两个文件是否一致?a.txt 和bb.txt 分别md5 看签名是否一致

  4. 破解网站的原理:穷举算法

  5. 为了解决穷举网站反推出明文,尽可能不使用123 6个8这种简单的明文

  6. 生成结果:始终是一个16进制,32位长度字符串

MD5加密认证流程

reg.html->用户名、密码->提交->后台web应用处理(业务层进行操作)
在做md5之前应该先进行加盐的操作
登录和注册中md5加盐要一致

public static void main(String[] args) {
   
   
   // 1. 创建securityManager安全管理器
   DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
   
好的,您可以参考以下代码实现: ``` import org.apache.shiro.authc.*; import org.apache.shiro.realm.Realm; import org.apache.shiro.util.ByteSource; import org.apache.shiro.util.StringUtils; import java.util.HashSet; import java.util.Set; public class MyRealm implements Realm { private static final String REALM_NAME = "MyRealm"; private static Set<User> users = new HashSet<>(); static { // 模拟两个用户 User user1 = new User("user1", "123456"); User user2 = new User("user2", "123456"); users.add(user1); users.add(user2); } @Override public String getName() { return REALM_NAME; } @Override public boolean supports(AuthenticationToken token) { return token instanceof UsernamePasswordToken; } @Override public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String) token.getPrincipal(); String password = new String((char[]) token.getCredentials()); // 根据用户名从数据库查询用户信息 User user = getUserByUsername(username); if (user == null) { throw new UnknownAccountException(); // 用户不存在 } // 判断密码是否匹配 String md5Password = ShiroUtils.md5(password, user.getSalt()); // 加盐MD5加密 if (!StringUtils.equals(md5Password, user.getPassword())) { throw new IncorrectCredentialsException(); // 密码错误 } // 验证通过,返回一个封装了用户信息的AuthenticationInfo对象 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, md5Password, getName()); info.setCredentialsSalt(ByteSource.Util.bytes(user.getSalt())); // 设置值 return info; } /** * 根据用户名从数据库查询用户信息 */ private User getUserByUsername(String username) { for (User user : users) { if (StringUtils.equals(username, user.getUsername())) { return user; } } return null; } /** * 用户类,包含用户名和密码 */ private static class User { private String username; private String password; private String salt; public User(String username, String password) { this.username = username; this.password = password; this.salt = ShiroUtils.getRandomSalt(); // 生成一个随机值 } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getSalt() { return salt; } public void setSalt(String salt) { this.salt = salt; } } } ``` 其中,ShiroUtils类中的md5和getRandomSalt方法的实现如下: ``` import org.apache.shiro.codec.Hex; import org.apache.shiro.crypto.hash.Md5Hash; import org.apache.shiro.util.ByteSource; import java.security.SecureRandom; public class ShiroUtils { /** * 对密码进行加盐MD5加密 * * @param password 密码 * @param salt 值 * @return 加密后的密码 */ public static String md5(String password, String salt) { return new Md5Hash(password, ByteSource.Util.bytes(salt), 2).toHex(); } /** * 生成一个随机值 * * @return 值 */ public static String getRandomSalt() { SecureRandom random = new SecureRandom(); byte[] saltBytes = new byte[16]; random.nextBytes(saltBytes); return Hex.encodeToString(saltBytes); } } ``` 调用方式如下: ``` // 创建一个SecurityManager DefaultSecurityManager securityManager = new DefaultSecurityManager(); // 设置Realm securityManager.setRealm(new MyRealm()); // 将SecurityManager设置到当前线程的环境中 SecurityUtils.setSecurityManager(securityManager); // 获取当前用户 Subject currentUser = SecurityUtils.getSubject(); // 创建一个用户名密码令牌 UsernamePasswordToken token = new UsernamePasswordToken("user1", "123456"); // 登录,即进行身份验证 currentUser.login(token); // 验证是否登录成功 if (currentUser.isAuthenticated()) { System.out.println("登录成功"); } else { System.out.println("登录失败"); } ``` 其中,UsernamePasswordToken的构造方法可以传入用户名和密码,也可以传入用户名、密码和是否记住我。您可以根据实际需要进行选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值