第四章 编码/加密(学习笔记)
4.1 编码/解码
base64
String str = "hello"; //编码 String base64Encode = Base64.encodeToString(str.getBytes()); System.out.println(base64Encode); //解码 String str2 = Base64.decodeToString(base64Encode); System.out.println(str2);
16进制
String str = "hello"; //编码 String base64Encode = Hex.encodeToString(str.getBytes()); System.out.println(base64Encode); //解码 String str2 = new String(Hex.decode(base64Encode.getBytes())); System.out.println(str2);
byte/String 互相转换
String str="hello"; byte[] b = CodecSupport.toBytes(str); System.out.println(b); String result = CodecSupport.toString(b); System.out.println(result);
4.2 散列算法
是一种不可逆的算法,如:MD5、SHA,一般进行散列时最好提供一个salt(盐)
String str = "hello"; String salt = "1234"; String md5 = new Md5Hash(str,salt).toString(); System.out.println(md5);
还可以指定散列次数 new Md5Hash(str,salt,2).toString(); 相当于进行了两次MD5加密
Sha256
String str = "hello"; String salt = "123"; String sha1 = new Sha256Hash(str, salt).toString();
使用SHA256算法生成相应的散列数据,另外还有如SHA1、SHA512算法。
通用的散列算法
String str = "hello"; String salt = "123"; //内部使用MessageDigest String simpleHash = new SimpleHash("SHA-1", str, salt).toString();
为了方便使用,Shiro提供了HashService,默认提供了DefaultHashService实现。
String str = "hello"; String salt = "1234";
String pubSalt = "123456"; DefaultHashService hashService = new DefaultHashService(); //默认算法SHA-512 hashService.setPrivateSalt(new SimpleByteSource(salt)); //设置私盐 hashService.setGeneratePublicSalt(true); hashService.setRandomNumberGenerator(new SecureRandomNumberGenerator()); //生成公盐 HashRequest request = new HashRequest.Builder() .setAlgorithmName("MD5").setSource(ByteSource.Util.bytes(str)) .setSalt(ByteSource.Util.bytes(pubSalt)).setIterations(2).build(); String hex = hashService.computeHash(request).toHex(); System.out.println(hex);
1.首先创建一个DefaultHashService ,默认使用SHA-512
2.可以通过hashAlgorithmName 属性修改算法
3.setPrivateSalt 设置一个私盐 会与传入的公盐产生一个新盐
4.generatePublicSalt 判断 在没有传入公盐的时候 自动生成个公盐
5.randomNumberGenerator 用于生成公盐
6.hashIterations 设计迭代次数 (加密多少次)
7.需要构建一个HashRequest,传入算法、数据、公盐、迭代次数。
4.3 加密/解密
AES
AesCipherService aesCipherService = new AesCipherService(); aesCipherService.setKeySize(128); //设置长度 //生成key Key key = aesCipherService.generateNewKey(); String test = "hello";
//加密 String encrptText = aesCipherService.encrypt(test.getBytes(), key.getEncoded()).toHex(); System.out.println(encrptText); //解密 String text2 = CodecSupport.toString(aesCipherService.decrypt(Hex.decode(encrptText), key.getEncoded()).getBytes()); System.out.println(text2);
4.4 PasswordService/CredentialsMatcher
Shiro提供了PasswordService 及credentialsMathcer 用于加密和验证密码服务
DefaultPasswordService配合PasswordMatcher实现简单的密码加密与验证服务
1. 定义Realm
private PasswordService passwordService; public void setPasswordService(PasswordService passwordService){ this.passwordService = passwordService; } @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.addRole("role1"); authorizationInfo.addRole("role2"); authorizationInfo.addObjectPermission(new BitPermission("+user+10")); authorizationInfo.addObjectPermission(new WildcardPermission("user1:*")); authorizationInfo.addStringPermission("+user2+10"); authorizationInfo.addStringPermission("user2:*"); return authorizationInfo; } @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken upToken = (UsernamePasswordToken) token; //获取用户名 String username = upToken.getUsername(); String password = String.valueOf(upToken.getPassword()); if(!"zhang".equals(username)) { throw new UnknownAccountException(); //如果用户名错误 } if(!"123".equals(password)) { throw new IncorrectCredentialsException(); //如果密码错误 } //如果身份认证验证成功,返回一个AuthenticationInfo实现; return new SimpleAuthenticationInfo(username, passwordService.encryptPassword(password), getName()); }
做项目的时候这个密码要在service 中进行加密保存在数据库
2. ini配置(shiro-passwordservice.ini)
[main] passwordService=org.apache.shiro.authc.credential.DefaultPasswordService hashService=org.apache.shiro.crypto.hash.DefaultHashService passwordService.hashService=$hashService hashFormat=org.apache.shiro.crypto.hash.format.Shiro1CryptFormat passwordService.hashFormat=$hashFormat hashFormatFactory=org.apache.shiro.crypto.hash.format.DefaultHashFormatFactory passwordService.hashFormatFactory=$hashFormatFactory passwordMatcher=org.apache.shiro.authc.credential.PasswordMatcher passwordMatcher.passwordService=$passwordService myRealm=com.zls.shiro.realm.MyRealm myRealm.passwordService=$passwordService myRealm.credentialsMatcher=$passwordMatcher securityManager.realms=$myRealm
2.1 passwordService使用DefaultPasswordService
2.2 hashService 默认使用DefaultHashService(默认SHA-256算法)
2.3 hashFormat对于用散列出的值进行格式化,默认使用Shiro1CryptFormat ,对于有salt的密码请自定义实现ParsableHashFormat然后把salt格式化到散列值中
2.4 hashFormatFactory用于根据散列值得到散列的密码和salt
2.5 passwordMatcher使用PasswordMatcher,其是一个CredentialsMatcher实现;
2.6 将credentialsMatcher赋值给myRealm,myRealm间接继承了AuthenticatingRealm,其在调用getAuthenticationInfo方法获取到AuthenticationInfo信息后,会使用credentialsMatcher来验证凭据是否匹配,如果不匹配将抛出IncorrectCredentialsException异常。
@Test public void testPasswordServiceWithMyRealm() { login("classpath:shiro-passwordservice.ini", "zhang", "123"); }