美文网首页
Shiro 加盐加密

Shiro 加盐加密

作者: 风吟空城 | 来源:发表于2018-11-09 17:26 被阅读0次

    开头一段废话

    加盐加密会使用户的密码受到相对安全的保护,比普通的MD5加密要好。用户数据暴露给了用户,因为有盐值的存在,也很难拿到用户的原始密码。即时拿到了,也会增加破解难度。

    Shiro权限框架有加盐加密的实现,下面就简单描述下自己实现的过程。

    盐值

    我使用的盐值是32的随机字符串,盐值越长,保密性相对越好。不过,有看到其他开发者说24位的盐值是考虑加密速度等因素后比较合适的。

    工具类

    public class ShiroUtil {
    
        /**
         * 生成32的随机盐值
         */
        public static String createSalt(){
            return UUID.randomUUID().toString().replaceAll("-", "");
        }
    
        /**
         * 加盐加密
         * @param srcPwd    原始密码
         * @param saltValue 盐值
         */
        public static String salt(Object srcPwd, String saltValue){
            return new SimpleHash("MD5", srcPwd, saltValue, 1024).toString();
        }
    
    }
    

    方法作用见注释,此处不做说明。

    后端加密

    本人采用的方案是在后端加密。即在创建用户时,生成随机盐值,然后将加密后的密码存入数据库。如:

    public class User {
        /**
         * ID
         */
        private String id;
    
        /**
         * 登录用户
         */
        @NotEmpty(message = "用户名:用户名不能为空")
        private String username;
    
        /**
         * 登录密码
         */
        @Length(min = 6, message = "密码:密码长度不能低于6位")
        @NotEmpty(message = "密码:密码不能为空")
        private String password;
    
        /**
         * 盐值
         */
        private String saltValue;
    
        /**
         * 手机号
         */
        private String mobile;
    
        /**
         * 昵称
         */
        private String nickname;
    
        /**
         * 是否冻结
         */
        private Integer isFrozen;
    
        /**
         * 创建时间
         */
        private Date createTime;
    
        public User() {
        }
    
        public User(String id, String username, String password, String saltValue, String mobile, String nickname,
                    Integer isFrozen, Date createTime) {
            this.id = id;
            this.username = username;
            this.password = password;
            this.saltValue = saltValue;
            this.mobile = mobile;
            this.nickname = nickname;
            this.isFrozen = isFrozen;
            this.createTime = createTime;
        }
    
        /**
         * 创建新的用户
         * @param username 用户名
         * @param password 密码
         * @param nickname 昵称
         * @param mobile   手机号
         */
        public static User createUser(String username, String password, String nickname, String mobile){
            String saleValue = ShiroUtil.createSalt();
            return new User(ShiroUtil.createSalt(), username, ShiroUtil.salt(password, ByteSource.Util.bytes(saleValue).toString()),
                    saleValue, mobile, nickname, 0, new Date());
        }
        //省略set/get方法
    }
    

    @NotEmpty等注解,采用的thymeleaf的表单校验,如果报错了,请删除该注解,或者在POM中引入依赖即可,如:

    <dependency>
      <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    

    Shiro认证

    用户加密完成后,在Shiro中认证时,加盐加密用户输入的密码,然后和库中的对比是否一致即可。如:

    public class MyRealm extends AuthorizingRealm {
    
        @Autowired
        private UserMapper userMapper;
    
    
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
            //todo:获取用户的权限
            return authorizationInfo;
        }
    
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
    
            User user = this.userMapper.selectByPrimaryKey(token.getUsername());
            if (user == null){
                throw new AuthenticationException("用户不存在!");
            }
            //盐值
            ByteSource salt = ByteSource.Util.bytes(user.getSaltValue());
            String saltPassword = ShiroUtil.salt(token.getPassword(), salt.toString());
            if (!user.getPassword().equals(saltPassword)){
                throw new AuthenticationException("输入密码不正确!");
            }
            if (user.getIsFrozen() == 0){
                throw new AuthenticationException("用户已冻结!");
            }
            //第4个参数是realm名称
            return new SimpleAuthenticationInfo(token.getPrincipal(), token.getPassword(), salt, getName());
        }
    
    }
    

    相关文章

      网友评论

          本文标题:Shiro 加盐加密

          本文链接:https://www.haomeiwen.com/subject/vzpoxqtx.html