1、shrio自带提供多种加密的方法:
散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法如MD5、SHA等。一般进行散列时最好提供一个salt(盐),比如加密密码“admin”,产生的散列值是“21232f297a57a5a743894a0e4a801fc3”,可以到一些md5 解密网站很容易的通过散列值得到密码“admin”,即如果直接对密码进行散列相对来说破解更容易,此时我们可以加一些只有系统知道的干扰数据,如用户名和ID(即盐);这样散列的对象是“密码+用户名+ID”,这样生成的散列值相对来说更难破解
2、加密的使用代码
public class ShiroTest {
//shiro提供了现成的加密类 Md5Hash
@Test
public void testMd5(){
//MD5加密
String password = new Md5Hash("1111").toString();
System.out.println("加密后:"+password);
//加盐 salt 默认一次散列
String password_salt=new Md5Hash("1111", "siggy").toString();
System.out.println("加盐后:"+password_salt);
//散列2次
String password_salt_2 = new Md5Hash("1111", "siggy", 2).toString();
System.out.println("散列2次:"+password_salt_2);
//使用SimpleHash
SimpleHash hash = new SimpleHash("MD5", "1111", "siggy", 2);
System.out.println("simpleHash:"+hash.toString());
}
}
3、自定义realm的实现课加密的
3.1带入相关的maven依赖
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>0.2.23</version>
</dependency>
</dependencies>
3.2 继承AuthorizingRealm,写自己的realm
public class MyRealm extends AuthorizingRealm {
@Override
public String getName() {
return "myRealm";
}
/**
* 身份检验
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
/**
* 获取用户名
*/
String username = (String)authenticationToken.getPrincipal();
/**
* 假设通过用户名从数据库获取用户密码
*/
String password = "78a5940ee29370a687489906a35abb2c";
String salt = "stx";
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,password, ByteSource.Util.bytes(salt),getName());
return simpleAuthenticationInfo;
}
/**
* 授权
* @param principalCollection
* @return
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
/**
* 获取用户名
*/
String username =(String)principalCollection.getPrimaryPrincipal();
/**
* 获取该用户对应的权限
*/
List<String> listRole = new ArrayList<String>();
listRole.add("user");
listRole.add("admin");
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
for (String role:listRole) {
authorizationInfo.addRole(role);
}
List<String> listPermssion = new ArrayList<String>();
listPermssion.add("user:add");
listPermssion.add("user:update");
for (String permssion:listPermssion) {
authorizationInfo.addStringPermission(permssion);
}
return authorizationInfo;
}
}
3.3配置ini文件
[main]
#配置凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.Md5CredentialsMatcher
credentialsMatcher.hashAlgorithmName=md5
credentialsMatcher.hashIterations=2
#配置自定义的realm
myRealm=com.feng.realm.MyRealm
myRealm.credentialsMatcher=$credentialsMatcher
#配置securityManager
securityManager=org.apache.shiro.mgt.DefaultSecurityManager
securityManager.realms=$myRealm
3.4写代码进行测试
public static void main(String args[]){
//1、创建工厂
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shrio.ini");
//2、通过工厂创建SercurityManager
SecurityManager securityManager = factory.getInstance();
//3、将SecurityManager设置进入SecurityUtils
SecurityUtils.setSecurityManager(securityManager);
//4、从SecurityUtils获取主体Subject
Subject subject = SecurityUtils.getSubject();
//5、登录名和密码
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("feng","111111");
try {
//6、登录
subject.login(usernamePasswordToken);
//7、判断登录情况
if(subject.isAuthenticated()){
System.out.println("登录成功");
}
if(subject.hasRole("user")){
System.out.println("拥有user权限");
}
if(subject.isPermitted("user:add")){
System.out.println("拥有:user:add");
}
if(subject.isPermitted("user:delete")){
System.out.println("拥有:user:delete");
}
} catch (AuthenticationException e) {
e.printStackTrace();
System.out.print("登录成失败");
}
}
4、以上自定义realm的时候需要注意几点
4.1写自定义realm时需要继承:AuthorizingRealm
4.2需要实现三个方法:
第一个:
@Override
public String getName() {
return "myRealm";
}
第二个:
/**
* 身份检验
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
/**
* 获取用户名
*/
String username = (String)authenticationToken.getPrincipal();
/**
* 假设通过用户名从数据库获取用户密码
*/
String password = "78a5940ee29370a687489906a35abb2c";
String salt = "stx";
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,password, ByteSource.Util.bytes(salt),getName());
return simpleAuthenticationInfo;
}
第三个:
/**
* 授权
* @param principalCollection
* @return
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
/**
* 获取用户名
*/
String username =(String)principalCollection.getPrimaryPrincipal();
/**
* 获取该用户对应的权限
*/
List<String> listRole = new ArrayList<String>();
listRole.add("user");
listRole.add("admin");
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
for (String role:listRole) {
authorizationInfo.addRole(role);
}
List<String> listPermssion = new ArrayList<String>();
listPermssion.add("user:add");
listPermssion.add("user:update");
for (String permssion:listPermssion) {
authorizationInfo.addStringPermission(permssion);
}
return authorizationInfo;
}
4.3在自定义realm中使用了加密,和盐值,在ini配置文件中需要设置凭证匹配器
#配置凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.Md5CredentialsMatcher
credentialsMatcher.hashAlgorithmName=md5
credentialsMatcher.hashIterations=2
#配置自定义的realm
myRealm=com.feng.realm.MyRealm
myRealm.credentialsMatcher=$credentialsMatcher