登录鉴权方案

我们在开发中需要用到对接口的登录鉴权,

首先后台会根据几个参数组成字符串+secretKey,用AES(ECB)加密算法来生成秘钥ticket,第三方访问的时候,带在提供的系统认证地址后面(列如http(s)://test.com?ticket=秘钥)

参数:这些参数包括时间戳,姓名,手机号,8位随机数,这些都是基本的,有的还需要根据实际业务场景添加一些信息,比如人员所在地,所在行政区划,年龄,职位信息等等。

字符串参数生成规则:

timeStamp=时间戳&mobile=89757&userName=柳如是&random=(8位随机数)

前端:获取应用认证地址后面的ticket参数,传给自己应用的后端去处理,处理成功则跳转,否则报错

后端:获取前端传过来的tcket,用secretKey来解密,获取相关的参数信息,如时间戳timeStamp可用来判断是否超时(可自行设置超时时间,超时可报错),手机号mobile可用来查询自己系统的用户,生成token等,验证成功后返回给前端,前端跳转到相应系统页面。

根据以上需求:我们来用代码实现一下:

(1)首先根据几个参数组成字符串+secretKey,用AES(ECB)加密算法来生成秘钥ticket

  

/**
 * AES加密解密工具类
 * @Author: zigao
 * @Date: 2021/6/6 9:27
 */
public class AesUtils {

   /**
    * aes解密
    * @param cliperText
    * @param secretKey
    * @return
    * @throws Exception
    */
     public static String aesDecrypt(String cliperText, String secretKey) throws Exception {
      byte[] raw = secretKey.getBytes();
      SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
      //Cipher对象实际完成加密操作
      Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
      cipher.init(Cipher.DECRYPT_MODE, skeySpec);
      // 先用base64解码
      byte[] encrypted1 = Base64.getDecoder().decode(cliperText);
      byte[] original = cipher.doFinal(encrypted1);
      String originalString = new String(original, "UTF-8");
      return originalString;
     }


    /**
     * aes加密
     * @param plainText
     * @param secretKey
     * @return
     * @throws Exception
     */
    public static String aesEncrypt(String plainText, String secretKey) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        byte[] raw = secretKey.getBytes();
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);

        byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));
        Base64.Encoder encoder = Base64.getEncoder();
        // 此处使用BASE64做转码
        return encoder.encodeToString(encrypted);
     }
   }
/**
 *  Ticket工具类
 * @Author: zigao
 * @Date: 2021/6/7 10:28
 */
public class TicketUtils {

    /**
     * 加盐(SECRET)
     */
    public static final String SECRET_KEY = "1dvFasdTGB&sdsd@";
    
    /**
     * 生成ticket
     * @param timeStamp
     * @param mobile
     * @param userName
     * @param random
     * @return
     * @throws Exception
     */
    public static String genernateTicket(long timeStamp, String mobile, String userName, String random) throws Exception {
        //生成字符串规则
        String content = "timeStamp=" + timeStamp + "&mobile=" + mobile + "&userName=" + userName + "&random=" + random;
        //字符串+secret_key进行AES加密
        String ticket = AesUtils.aesEncrypt(content,SECRET_KEY);
        return ticket;
    }


}

我们来测试下:

 /**
     * 获取ticket
     *
     * @param
     * @return
     */
    @PostMapping("/getTicket")
    public ResponseMessage getTicket() {
        ResponseMessage responseMessage = new ResponseMessage(0);
        try {
             //生成时戳
            long timeStamp = System.currentTimeMillis();
             //手机号
            String mobile = "89757";
             //用户名
            String userName = "柳如是";
             //随机数(8位,我这里做测试,正式开发建议用随机数工具类)
            String random = "wsxc45f1";
            String ticket = TicketUtils.genernateTicket(timeStamp, mobile, userName, random);
            responseMessage.setMessage(ticket);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        return responseMessage;
    }

 ticket生成成功。

(2)获取前端传过来的tcket,用secretKey来解密,获取相关的参数信息,生成token

  

/**
 *  登录解析工具类
 * @Author: zigao
 * @Date: 2021/6/7 11:07
 */
public class SdkUtils {


    private final static Logger logger = LoggerFactory.getLogger(SdkUtils.class);


    /**
     * 加盐(SECRET)
     */
    public static final String SECRET_KEY = "1dvFasdTGB&sdsd@";

    /**
     * 解析
     * @param ticket
     * @param
     * @return
     * @throws Exception
     */
    public static Map validateTicket(String ticket) throws Exception {
        //进行解密+secretKey
        String resultJson = AesUtils.aesDecrypt(ticket, SECRET_KEY);
        logger.info("resultJson解密输出==>" + resultJson);
        //字符串转成map
        Map map = SdkUtils.getMap(resultJson);
        return map;
    }

    /**
     * 字符串转map集合
     * @param strValue
     * @return
     */
    public static Map getMap(String strValue){
        Map map = new HashMap();
        String[] text = strValue.split("&"); // 转换为数组
        for (String str : text) {
            String[] keyText = str.split("="); // 转换key与value的数组
            if (keyText.length < 1) {
                continue;
            }
            String key = keyText[0]; // key
            String value = keyText[1]; // value
            map.put(key, value);
        }
        return map;
    }


  }
/**
 *  token信息
 * @Author: zigao
 * @Date: 2021/6/7 13:44
 */
@Data
public class UserToken implements Serializable {

    //token 会话令牌
    String token;

    //用户编号
    String mobile;

    //用户名
    String userName;



}

 /**
     * 获取token
     *
     * @param
     * @return
     */
    @PostMapping("/getToken")
    public ResponseMessage getToken(@RequestBody Map map) {
        ResponseMessage responseMessage = new ResponseMessage(0);
        try {
            //获取ticket
            String ticket = (String) map.get("ticket");
            Map mapValue = SdkUtils.validateTicket(ticket);
            UserToken userToken = new UserToken();
            userToken.setToken(UUID.randomUUID().toString());
            userToken.setUserName(mapValue.get("userName").toString());
            userToken.setMobile(mapValue.get("mobile").toString());
            responseMessage.setMessage(userToken);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
        return responseMessage;
    }

登录鉴权方案_第1张图片

你可能感兴趣的:(解决方案,前端,java,开发语言)