使用Shiro1.2中的PasswordService实现密码加密存储和比对

本文介绍了如何在Shiro1.2中利用PasswordService进行密码加密存储和验证,强调了它相较于以往版本的便利性。通过示例代码展示了shiro.ini配置以及用户登录和注册过程中的密码处理方式,包括对比对类的修正以适应与JDBC存储的密文进行匹配。

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

在Shiro之前的版本中,密码加密一般采用如下代码:
String digestString = new Sha256Hash(password, salt, numIterations).toBase64();

密码比对一般采用HashedCredentialsMatcher或Sha256CredentialsMatcher等相关比对类,在新版1.2中,增添了一项重要的功能就是密码服务,使得加密和比对更加方便。

比如:

加密就只需要密码这个参数
PasswordService svc = new DefaultPasswordService(); 
svc.encryptPassword(password);
比对就用如下语句:encrypted是密文
svc.passwordsMatch(password, encrypted);

看到上述代码,一个感觉就是:程序逻辑很清晰。

同样的,在1.2中,同样可以通过密码服务配置,实现与jdbc中的密码密文进行比对。直接上代码了:

以下是shiro.ini

passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
passwordMatcher = com.helloweb.shm.PasswordMatcherEx
passwordMatcher.passwordService = $passwordService

ds = com.mysql.jdbc.jdbc2.optional.MysqlDataSource
ds.serverName = 192.168.1.101
ds.user = root  
ds.password =******  
ds.databaseName = helloweb  
ds.url = jdbc:mysql://192.168.1.101:3306/helloweb  

jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm 
jdbcRealm.permissionsLookupEnabled = true  
jdbcRealm.authenticationQuery = SELECT password FROM user WHERE username = ?  
jdbcRealm.dataSource = $ds 
jdbcRealm.credentialsMatcher = $passwordMatcher

authc.loginUrl=/login.jsp
[urls]
/admin/**=authc

说明,com.helloweb.shm.PasswordMatcherEx是我对org.apache.shiro.authc.credential.PasswordMatcher进行了修正,重写了getStoredPassword()方法,如下:

package com.helloweb.shm;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.credential.PasswordMatcher;

public class PasswordMatcherEx extends PasswordMatcher {
	@Override
	protected Object getStoredPassword(AuthenticationInfo storedAccountInfo) {
		Object stored = super.getStoredPassword(storedAccountInfo);

		if (stored instanceof char[]) {
			stored = String.valueOf((char[]) stored);
		}
		return stored;
	}
}

重写的原因是,JdbcRealm返回给PasswordMatcher的哈希值被保存为char[]型,而PasswordMatcher 却希望getCredentials()返回一个String或Hash。

用户登录代码如下:

public String doLogin() {
        Subject currentuser = SecurityUtils.getSubject();
	UsernamePasswordToken token = new UsernamePasswordToken(username,
			password);
	try {
		if (currentuser.isAuthenticated())
			currentuser.logout();
		currentuser.login(token);
		return SUCCESS;
	} catch (Exception e) {
		addActionError("用户名或密码有误");
		return ERROR;
	}
}

用户注册代码如下:

public String doReg() {
	if (isLegal()) {
		User user = new User();
		PasswordService svc = new DefaultPasswordService();
		String encrypted = svc.encryptPassword(password);
		user.setUsername(username);
		user.setPassword(encrypted);
		UserDAO ud = new UserDAO();
		if (!ud.findByUsername(username).isEmpty()) {
			addActionError("用户名已存在!");
			return ERROR;
		}
		ud.save(user);
		addActionMessage("注册成功!");
	} else {
		addActionError("注册信息填写有误!");
		return ERROR;
	}
	return SUCCESS;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值