在shiro的基础上写一个登录验证+MD5的MyRealm
时间: 2024-03-22 21:38:47 浏览: 14
好的,您可以参考以下代码实现:
```
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的构造方法可以传入用户名和密码,也可以传入用户名、密码和是否记住我。您可以根据实际需要进行选择。