对于密码,有很多种加密方式散列是其中 最常用的,shiro提供了直接支持。
<dependencies>
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-coreartifactId>
<version>1.2.4version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-log4j12artifactId>
<version>1.7.15version>
dependency>
<dependency>
<groupId>commons-logginggroupId>
<artifactId>commons-loggingartifactId>
<version>1.2version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
dependencies>
Md5Hash(Object source, Object salt, int hashIterations)
SimpleHash(String algorithmName, Object source, Object salt, int hashIterations)
参数含意:
source: 要散列的值(这里是明文密码)
salt: 盐,用于与source一起散列的值,一般随机生成,用于防止暴力破解
hashIterations: 散列的次数
algorithmName: simpleHash是其它散列的父类(如下图),如果要用simpleHash就要告诉shiro使用哪种hash方式
log4j.properties
log4j.rootLogger=DEBUG, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
shiro-realm-md5.ini
[main]
#注入凭证匹配器
cridentialMatcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher
cridentialMatcher.hashAlgorithmName = MD5
cridentialMatcher.hashIterations = 3
#注入自定义的realm
hashRealm = xyz.mrwood.study.realm.HashRealm
hashRealm.credentialsMatcher = $cridentialMatcher
securityManager.realms = $hashRealm
User.java(模拟数据库中的表)
package xyz.mrwood.study.model;
/**
* Created by Administrator on 2016/2/16.
*/
public class User {
private String username;
private String password;
private String salt;
public User(String username, String password, String salt) {
this.username = username;
this.password = password;
this.salt = salt;
}
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;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", salt='" + salt + '\'' +
'}';
}
}
HashRealm.java
package xyz.mrwood.study.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.crypto.hash.Md5Hash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import xyz.mrwood.study.model.User;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Administrator on 2016/2/16.
*/
public class HashRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//获得主体(帐号)
String principal = (String) authenticationToken.getPrincipal();
//模拟数据库
Map users = new HashMap<>();
users.put("kiwi", new User("kiwi", new Md5Hash("22222", "324", 3).toString(), "324"));
users.put("fly", new User("fly", new Md5Hash("111111", "123", 3).toString(), "123"));
//验证帐号是否存在
if (users.containsKey(principal)){
User user = users.get(principal);
System.out.printf(user.toString());
//在realm中只要判断帐号是否存在,密码是否正确交给shiro比较
return new SimpleAuthenticationInfo(principal, user.getPassword(), ByteSource.Util.bytes(user.getSalt()), getName());
}else{
return null;
}
}
}
AuthenticationTest.java
package xyz.mrwood.study.authentication;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;
/**
* Created by Administrator on 2016/2/12.
*/
public class AuthenticationTest {
@Test
public void testHash(){
// 构建SecurityManager对象
Factory factory = new IniSecurityManagerFactory("classpath:shiro-realm-md5.ini");
SecurityManager securityManager = factory.getInstance();
// 设置SecurityManager进入运行环境
SecurityUtils.setSecurityManager(securityManager);
// 构建主体对象
Subject subject = SecurityUtils.getSubject();
// 封装帐号密码对象
// 密码传明文,所有如果要用这个以后客户端不能再加密了
AuthenticationToken token = new UsernamePasswordToken("kiwi", "22222");
// 提交验证
try {
subject.login(token);
} catch (IncorrectCredentialsException e) {
System.out.println("错误的凭证!");
} catch (UnknownAccountException e){
System.out.println("未知帐号!");
}
System.out.println("认证:" + subject.isAuthenticated());
}
}