一、散列算法
散列算法一般用于生成数据的摘要信息,是一种不可逆的算法,一般适合存储密码之类的数据,常见的散列算法有MD5,SHA等。一般进行散列时最好提供一个salt(盐),比如
使用MD5加密后的结果:
e10adc3949ba59abbe56e057f20f883e
使用MD5加密并加盐后的结果:19a45a53e8924a742f77183b8878a5fb
使用MD5加密加盐并散列两次后的结果:b4f48723743cc5bfa7c1716296703ce1
简单的可以破解出来https://cmd5.com/,但是原则不可逆。
1、散列算法工具类
package com.sxt.utils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.crypto.hash.Sha1Hash;
public class MD5Utils {
public static void main(String[] args) {
String source = "123456";
Md5Hash hash1 = new Md5Hash(source);
System.out.println(hash1);//e10adc3949ba59abbe56e057f20f883e
Md5Hash hash2 = new Md5Hash(source,"武汉");
System.out.println("MD5加密并且加盐的结果:"+hash2);//3ca8b47ced5ea7588c917c52a3ccbdd7
Md5Hash hash3 = new Md5Hash(source,"武汉",2);
System.out.println("MD5加密并且加盐并且加密两次的结果:"+hash3);//a289a660a2c4521bb2894445a7e77667
Sha1Hash hash4 = new Sha1Hash("123456");
System.out.println(hash4);
}
/**
* 工具类1:使用Md5Hash对密码进行加密
* @param source 要加密的明文
* @param salt 盐
* @param hashIterations 散列次数
* @return
*/
public static String md5(String source,Object salt,Integer hashIterations){
return new Md5Hash(source,salt,hashIterations).toString();
}
/**
* 工具类2:使用Sha1Hash对密码进行加密
* @param source 要加密的明文
* @param salt 盐
* @param hashIterations 散列次数
* @return
*/
public static String sha1(String source,Object salt,Integer hashIterations){
return new Sha1Hash(source,salt,hashIterations).toString();
}
}
二、凭证配置
1、方式1
(1)无ini文件
(2)UserRealm.java
//public class UserRealm extends AuthenticatingRealm {
public class UserRealm extends AuthorizingRealm {
private UserService userService=new UserServiceImpl();
private RoleService roleService=new RoleServiceImpl();
private PermissionService permissonService=new PermissionServiceImpl();
public UserRealm(){
//注册凭证匹配器
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
//指定加密算法
credentialsMatcher.setHashAlgorithmName("md5");
credentialsMatcher.setHashIterations(2);//设置散列次数
setCredentialsMatcher(credentialsMatcher);
}
/**
* 做认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//可以获取用户传递过来的数据,用户名,密码
String username=token.getPrincipal().toString();
String password = new String((char[])token.getCredentials());
//封装用户,角色,权限对象
User user=userService.queryUserByUserName(username);
Collection<String> roles = roleService.queryRoleByUserName(username);
Collection<String> permissions = permissonService.queryPermissionByUserName(username);
ActiverUser activerUser = new ActiverUser(user,roles,permissions);
/**
* 以前登陆的逻辑是 把用户和密码全部发到数据库 去匹配
* 在shrio里面是先根据用户名把用户对象查询出来,再来做密码匹配
*/
if(null!=user) {
/**
* 参数说明
* 参数1:可以传到任意对象
* 参数2:从数据库里面查询出来的密码
* 参数3:当前类名
*/
//SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(activerUser, user.getPwd(), this.getName());
/**
* 参数说明
* 参数1:可以传到任意对象
* 参数2:从数据库里面查询的散列之后密码
* 参数3:盐
* 参数4:当前类名
*/
ByteSource credentialsSalt =ByteSource.Util.bytes( "武汉");
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(activerUser,user.getPwd(),credentialsSalt,this.getName());
return info;
}else {
//用户不存在 shiro会抛 UnknowAccountException
return null;
}
}
@Override//做授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
ActiverUser activerUser = (ActiverUser) principalCollection.getPrimaryPrincipal();
//添加角色和权限在info中
if (activerUser.getRoles()!=null&&activerUser.getRoles().size()>0){
info.addRoles(activerUser.getRoles());
}
if (activerUser.getPermission()!=null&&activerUser.getPermission().size()>0){
info.addStringPermissions(activerUser.getPermission());
}
/*//如果是root,则授予所有权限
if (activerUser.getUser().getType()==0){
info.addStringPermission("*:*");
}*/
return info;
}
}
(3)main方法
public class TestAuthenticationApp {
// 日志输出工具
private static final transient Logger log = LoggerFactory.getLogger(TestAuthenticationApp.class);
public static void main(String[] args) {
String username = "zhangsan";
String password = "123456";
log.info("My First Apache Shiro Application");
// 1、创建安全管理器的工厂对象 org.apache.shiro.mgt.SecurityManager;不能使用java.lang.SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
// 2、使用工厂创建安全管理器DefaultSecurityManager(不同)
DefaultSecurityManager securityManager = (DefaultSecurityManager) factory.getInstance();
//3、创建UserRealm
UserRealm realm = new UserRealm();
注册凭证匹配器
//HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
//指定加密算法
//credentialsMatcher.setHashAlgorithmName("md5");
设置散列次数
//credentialsMatcher.setHashIterations(2);
//realm.setCredentialsMatcher(credentialsMatcher);
// 4、给securityManager注入userRealm
securityManager.setRealm(realm);
// 6、把当前的安全管理器绑定当到线的线程
SecurityUtils.setSecurityManager(securityManager);
// 7、使用SecurityUtils.getSubject得到主体对象
Subject subject = SecurityUtils.getSubject();
// 8、封装用户名和密码
AuthenticationToken token = new UsernamePasswordToken(username, password);
// 9、得到认证
try {
subject.login(token);
System.out.println("认证通过");
//用于接收UserRealm中SimpleAuthenticationInfo方法的第一个参数Object
//Object principal = subject.getPrincipal();
//System.out.println(principal);
} catch (IncorrectCredentialsException e) {
System.out.println("密码不正确");
} catch (UnknownAccountException e) {
System.out.println("用户名不存在");
}
//判断是否有role1角色
boolean hasRole1 = subject.hasRole("role1");
System.out.println("是否有role1的角色:"+hasRole1);
//判断是否有user:query权限
boolean b = subject.isPermitted("user:query");
System.out.println("是否有user:query的角色:"+b);
}
}
/**
* 在spring里面如何配置
* 1,配置凭证匹配器
* <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
* <property name="hashAlgorithmName" value="md5">
* <property name="hashIterations" value="2">
* </bean>
* 2,配置realm
* <bean id="realm" class="com.sxt.realm.UserRealm">
* <property name="credentialsMatcher" ref="credentialsMatcher">
* </bean>
* 3,配置SecurityManager
* <bean id="securityManager" class="org.apache.shiro.mgt.DefaultSecurityManager">
* <propery name="realm" ref="realm">
* </bean>
*
*
*/
2、方式2
(1)无ini文件
(2)主方法
public class TestAuthenticationApp {
// 日志输出工具
private static final transient Logger log = LoggerFactory.getLogger(TestAuthenticationApp.class);
public static void main(String[] args) {
String username = "zhangsan";
String password = "123456";
log.info("My First Apache Shiro Application");
// 1、创建安全管理器的工厂对象 org.apache.shiro.mgt.SecurityManager;不能使用java.lang.SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
// 2、使用工厂创建安全管理器DefaultSecurityManager(不同)
DefaultSecurityManager securityManager = (DefaultSecurityManager) factory.getInstance();
//3、创建UserRealm
UserRealm realm = new UserRealm();
//注册凭证匹配器
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
指定加密算法
credentialsMatcher.setHashAlgorithmName("md5");
//设置散列次数
credentialsMatcher.setHashIterations(2);
realm.setCredentialsMatcher(credentialsMatcher);
// 4、给securityManager注入userRealm
securityManager.setRealm(realm);
// 6、把当前的安全管理器绑定当到线的线程
SecurityUtils.setSecurityManager(securityManager);
// 7、使用SecurityUtils.getSubject得到主体对象
Subject subject = SecurityUtils.getSubject();
// 8、封装用户名和密码
AuthenticationToken token = new UsernamePasswordToken(username, password);
// 9、得到认证
try {
subject.login(token);
System.out.println("认证通过");
//用于接收UserRealm中SimpleAuthenticationInfo方法的第一个参数Object
//Object principal = subject.getPrincipal();
//System.out.println(principal);
} catch (IncorrectCredentialsException e) {
System.out.println("密码不正确");
} catch (UnknownAccountException e) {
System.out.println("用户名不存在");
}
//判断是否有role1角色
boolean hasRole1 = subject.hasRole("role1");
System.out.println("是否有role1的角色:"+hasRole1);
//判断是否有user:query权限
boolean b = subject.isPermitted("user:query");
System.out.println("是否有user:query的角色:"+b);
}
/**
* 在spring里面如何配置
* 1.配置
*/
}
/**
* 在spring里面如何配置
* 1,配置凭证匹配器
* <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
* <property name="hashAlgorithmName" value="md5">
* <property name="hashIterations" value="2">
* </bean>
* 2,配置realm
* <bean id="realm" class="com.sxt.realm.UserRealm">
* <property name="credentialsMatcher" ref="credentialsMatcher">
* </bean>
* 3,配置SecurityManager
* <bean id="securityManager" class="org.apache.shiro.mgt.DefaultSecurityManager">
* <propery name="realm" ref="realm">
* </bean>
*
*
*/
3、方式3
(1)ini文件
[main]
##创建凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
credentialsMatcher.hashAlgorithmName=md5
credentialsMatcher.hashIterations=2
##HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
##指定加密算法
##credentialsMatcher.setHashAlgorithmName("md5");
##credentialsMatcher.setHashIterations(2);//设置散列次数
##setCredentialsMatcher(credentialsMatcher);
##创建userRealm对象
userRealm=com.sxt.realm.UserRealm
##给userRealm注入凭证匹配器
userRealm.credentialsMatcher=$credentialsMatcher
##把当前对象给安全管理器
##securityManager=org.apache.shiro.mgt.DefaultSecurityManager
securityManager.realm=$userRealm
(2)主方法
public static void main(String[] args) {
String username = "zhangsan";
String password = "123456";
log.info("My First Apache Shiro Application");
// 1、创建安全管理器的工厂对象 org.apache.shiro.mgt.SecurityManager;不能使用java.lang.SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
// 2、使用工厂创建安全管理器DefaultSecurityManager(不同)
DefaultSecurityManager securityManager = (DefaultSecurityManager) factory.getInstance();
//3、创建UserRealm
//UserRealm realm = new UserRealm();
注册凭证匹配器
//HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
//指定加密算法
//credentialsMatcher.setHashAlgorithmName("md5");
设置散列次数
//credentialsMatcher.setHashIterations(2);
//realm.setCredentialsMatcher(credentialsMatcher);
// 4、给securityManager注入userRealm
//securityManager.setRealm(realm);
// 6、把当前的安全管理器绑定当到线的线程
SecurityUtils.setSecurityManager(securityManager);
// 7、使用SecurityUtils.getSubject得到主体对象
Subject subject = SecurityUtils.getSubject();
// 8、封装用户名和密码
AuthenticationToken token = new UsernamePasswordToken(username, password);
// 9、得到认证
try {
subject.login(token);
System.out.println("认证通过");
//用于接收UserRealm中SimpleAuthenticationInfo方法的第一个参数Object
//Object principal = subject.getPrincipal();
//System.out.println(principal);
} catch (IncorrectCredentialsException e) {
System.out.println("密码不正确");
} catch (UnknownAccountException e) {
System.out.println("用户名不存在");
}
//判断是否有role1角色
boolean hasRole1 = subject.hasRole("role1");
System.out.println("是否有role1的角色:"+hasRole1);
//判断是否有user:query权限
boolean b = subject.isPermitted("user:query");
System.out.println("是否有user:query的角色:"+b);
}
}
/**
* 在spring里面如何配置
* 1,配置凭证匹配器
* <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
* <property name="hashAlgorithmName" value="md5">
* <property name="hashIterations" value="2">
* </bean>
* 2,配置realm
* <bean id="realm" class="com.sxt.realm.UserRealm">
* <property name="credentialsMatcher" ref="credentialsMatcher">
* </bean>
* 3,配置SecurityManager
* <bean id="securityManager" class="org.apache.shiro.mgt.DefaultSecurityManager">
* <propery name="realm" ref="realm">
* </bean>
*
*
*/