【Shiro】shiro加密

⽤户的密码是不允许明⽂存储的,因为⼀旦数据泄露,⽤户的隐私信息会完全暴露。所以密码必须结果加密,⽣成密⽂,然后数据库中只存储⽤户的密码的密⽂。

在加密过程中需要使⽤到⼀些"不可逆加密",如 md5,sha等
所谓不可逆是指:

加密函数A, 明⽂ “abc”,

A("abc") = "密⽂"

不能通过 “密⽂” 反推出 “abc”,即使密⽂泄露密码仍然安全。

1. shiro加密介绍

shiro⽀持hash(散列)加密,常见的如 md5, sha等

  • 基本加密过程
    md5(明⽂),sha(明⽂) 得到明⽂的密⽂,但明⽂可能⽐较简单,导致密⽂容易被破解。

  • 加盐加密过程
    系统⽣成⼀个随机salt=“xxxxxx”, md5(明⽂+salt) ,sha(明⽂+salt),则提升了密⽂的复杂度。

  • 加盐多次迭代加密过程
    如果迭代次数为2,则加密2次: md5(明⽂+salt)=密⽂a , md5(密⽂a+salt)=最终密⽂
    sha(明⽂+salt)=密⽂a , sha(密⽂a+salt)=最终密⽂
    则进⼀步提升了密⽂的复杂度,和被破解的难度。

加密过程中建议使⽤salt,并指定迭代次数,迭代次数的建议值1000+

  • 实例代码:
String password="abc";//密码明⽂
String salt=UUID.randomUUID().toString();//盐
Integer iter = 1000;//迭代次数
String pwd = new Md5Hash(password, salt,iter).toString(); //md5加密
String pwd = new Md5Hash(password, salt, iter).toBase64(); //加密后转base64
String pwd = new Sha256Hash(password, salt, iter).toString();//sha256加密
String pwd = new Sha256Hash(password, salt, iter).toBase64();//加密后转base64
String pwd = new Sha512Hash(password, salt, iter).toString();//sha256加密
String pwd = new Sha512Hash(password, salt, iter).toBase64()//加密后转base64

2. 加密

增加⽤户,或修改⽤户密码时,涉及到密码的加密

在注册⽤户的业务中,对⽤户提交的密码加密即可。
注意:我们需要在用户表中加⼀列【 salt varchar(50) 】,⽤于存储每个⽤户的盐(即随机字符串)。

class UserServiceImpl implements UserService{
    @Autowired
    private UserDAO userDAO;
    public void createUser(User user){
        user.setSalt(UUID.randomUUID().toString());//设置随机盐
        //设置加密属性:sha256算法,随机盐,迭代1000次
        Sha256Hash sha256Hash = new Sha256Hash(user.getPassword(),user.getSalt(),1000);
        //将⽤户信息 (包括密码的密⽂ 和 盐) 存⼊数据库
        user.setPassword(sha256Hash.toBase64());//密⽂采⽤base64格式化
        userDAO.createUser(user);
    }
}

3. 密码比对

在登录认证身份的时候,我们需要将登录的密码与正确的密码进行比对,所以我们只需要将登录用的密码加入相同的盐,并进行相同次数的迭代,最后进行比对就行了。

在shiro中,我们只需要声明加密方式,加入的盐,以及次数即可。

首先指定比对器

[main]
...
#声明密码⽐对器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
credentialsMatcher.hashAlgorithmName=sha-256
credentialsMatcher.hashIterations=1000
# true=hex格式 false=base64格式
credentialsMatcher.storedCredentialsHexEncoded=false
#⽐对器关联给realm,则realm中对⽤户做身份认证时,可以使⽤加密⽐对器,对密⽂做⽐对
realm1 = com.siyi.realm.MyRealm
realm1.credentialsMatcher=$credentialsMatcher
#realm关联给securityManager
securityManager.realms=$realm1

4. 更改自定义Realm

通过上面的配置我们很容易可以看出还缺少盐的加入。而我们的salt本身就是随机的所以不可能写在配置文件中。所以我们将在程序中从数据库中获取盐,并加入到认证方法中。

doGetAuthenticationInfo⽅法的返回值需要做修改。

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws
    AuthenticationException {
    String username = (String) token.getPrincipal();
    UserService userService =
        (UserService)ContextLoader.getCurrentWebApplicationContext().getBean("userService");
    User user = userService.queryUser(username);
    System.out.println("user:"+user);
    if(user==null){
        System.out.println("⽤户不存在");
        throw new UnknownAccountException("username:"+username+"不存在");
    }
    //以上逻辑不变
    //在最后返回⽤户认证info时,添加⼀个属性:ByteSource.Util.bytes(user.getSalt()) = 盐
    //⽤于密码⽐对
    return new SimpleAuthenticationInfo(user.getUsername(),
                                        user.getPassword(),
                                        ByteSource.Util.bytes(user.getSalt()),
                                        getName());
}

这样,可以进⾏注册,注册中已经会加密密码。
然后登陆认证身份,认证时realm会调⽤⽐对器⽐对密⽂。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值