第四章 编码/加密(学习笔记)

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");
 }

 

posted @ 2018-04-02 14:19  暖少年  阅读(238)  评论(0编辑  收藏  举报