若依Vue前后端分离版本自定义加密方式


最近在学习若依vue前后端分离版的脚手架,想使用Md5加密方式实现登陆验证,现在记录一下解决过程。
若依是个很好的脚手架,单体版若依使用shiro实现安全认证与权限控制,而分离版使用的是Spring Security实现,我们阅读若依源码时可以发现,若依的framework模块下有个security包,这里面是若依自己封装的认证失败处理类等,与加密登录验证无关,跳过。我们需要关注的是framework模块下的config包下的SecurityConfig类,里面有两个方法:

/**
     * 强散列哈希加密实现
     */
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder()
    {
        return new BCryptPasswordEncoder();
    }

    /**
     * 身份认证接口
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception
    {
        auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
    }

Spring Security通过passwordEncoder()进行身份认证,参数为PasswordEncoder接口类,也就是说传入的参数是需要实现PasswordEncoder接口的类,BCryptPasswordEncoder类是强散列哈希类,关于这个类的说明我们在此不介绍,它是一种哈希算法,详情自行百度,既然知道身份认证使用的方法了,咱们自定义一个Md5加密方法:

/**
     * Md5加密实现
     * @return
     */
    @Bean
    public Md5PasswordEncoder md5PasswordEncoder(){
        return new Md5PasswordEncoder();
    }

在common模块下新建一个类Md5PasswordEncoder并实现PasswordEncoder接口

public class Md5PasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence rawPassword) {
        return Md5Utils.hash(rawPassword.toString());
    }

    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        return Md5Utils.hash(rawPassword.toString()).equals(encodedPassword);
    }
}

若依自己封装了一个Md5加密的util类,我们不用自己封装了,但还是把代码贴出来吧

package com.ruoyi.common.utils.sign;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Md5加密方法
 * 
 * @author ruoyi
 */
public class Md5Utils
{
    private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);

    private static byte[] md5(String s)
    {
        MessageDigest algorithm;
        try
        {
            algorithm = MessageDigest.getInstance("MD5");
            algorithm.reset();
            algorithm.update(s.getBytes("UTF-8"));
            byte[] messageDigest = algorithm.digest();
            return messageDigest;
        }
        catch (Exception e)
        {
            log.error("MD5 Error...", e);
        }
        return null;
    }

    private static final String toHex(byte hash[])
    {
        if (hash == null)
        {
            return null;
        }
        StringBuffer buf = new StringBuffer(hash.length * 2);
        int i;

        for (i = 0; i < hash.length; i++)
        {
            if ((hash[i] & 0xff) < 0x10)
            {
                buf.append("0");
            }
            buf.append(Long.toString(hash[i] & 0xff, 16));
        }
        return buf.toString();
    }

    public static String hash(String s)
    {
        try
        {
            return new String(toHex(md5(s)).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
        }
        catch (Exception e)
        {
            log.error("not supported charset...{}", e);
            return s;
        }
    }
}

好了,到这我们实现了登录的密码验证以md5的方式验证,但还有一步,那就是加密,比如注册账户、修改密码的时候,我们需要将密码加密以后存入数据库,若依的加密方法在common模块的SecurityUtils类中,我们将原来的方法注释掉,替换为使用Md5加密

/**
     * 生成BCryptPasswordEncoder密码
     * 修改为md5加密
     *
     * @param password 密码
     * @return 加密字符串
     */
    public static String encryptPassword(String password)
    {
        //BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        //return passwordEncoder.encode(password);
        return Md5Utils.hash(password);
    }

    /**
     * 判断密码是否相同
     *
     * @param rawPassword 真实密码
     * @param encodedPassword 加密后字符
     * @return 结果
     */
    public static boolean matchesPassword(String rawPassword, String encodedPassword)
    {
//        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
//        return passwordEncoder.matches(rawPassword, encodedPassword);
        Md5PasswordEncoder md5PasswordEncoder=new Md5PasswordEncoder();
        return md5PasswordEncoder.matches(rawPassword,encodedPassword);
    }

这样就修改了若依框架的密码加密、登陆验证方式了,我也从中学习到了SpringSecurity的使用方法与登录流程原理。