为了账号安全,请及时绑定邮箱和手机立即绑定

使用带有 Spring Security 的 Telegram 登录

使用带有 Spring Security 的 Telegram 登录

慕桂英3389331 2023-06-21 14:52:12
我正在尝试在 Spring Boot 应用程序上实现使用 Telegram 登录(https://core.telegram.org/widgets/login),但遇到了问题。我一直在尝试实施他们提供的 PHP 代码来验证身份验证,但出了点问题,我无法理解是什么。所以,这就是 PHP 上的代码secret_key = SHA256(<bot_token>)if (hex(HMAC_SHA256(data_check_string, secret_key)) == hash) {  // data is from Telegram}Data-check-string 是所有接收到的字段的串联,按字母顺序排序,格式key=<value>为使用换行符('\n',0xA0)作为分隔符 - 例如,'auth_date=<auth_date>\nfirst_name=<first_name>\nid=<id>\nusername=<username>.所以,我所做的是:@AllArgsConstructor@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)public class AuthenticationRequest {  @NotNull  private Long authDate;  private String firstName;  @NotEmpty  private String id;  private String lastName;  private String photoUrl;  private String username;  @NotEmpty  private String hash;  @Override  public String toString() {    final var data = new StringBuilder();    for (final Field field : getClass().getDeclaredFields()) {      try {        if (!field.getName().equals("hash") && field.get(this) != null) {          final var fieldName = CaseFormat.LOWER_CAMEL              .to(CaseFormat.LOWER_UNDERSCORE, field.getName());          data.append(fieldName).append("=").append(field.get(this)).append("\\n");        }      } catch (IllegalAccessException e) {        e.printStackTrace();      }    }    return data.substring(0, data.length() - 2);  }}还有这两个方法:private static String hmacSha256(final String data, final byte[] secret) {    try {      Mac sha256Hmac = Mac.getInstance("HmacSHA256");      SecretKeySpec secretKey = new SecretKeySpec(secret, "HmacSHA256");      sha256Hmac.init(secretKey);      byte[] signedBytes = sha256Hmac.doFinal(data.getBytes());      return bytesToHex(signedBytes);    } catch (NoSuchAlgorithmException | InvalidKeyException ex) {      return null;    }你能告诉我我做错了什么吗?也许我完全误解了验证身份验证数据的方式,或者我错过了什么?
查看完整描述

2 回答

?
蓝山帝景

TA贡献1843条经验 获得超7个赞

试试这个,代码有点难看,但效果很好!


public boolean verifyAuth(JsonObject Telegram_User){


    String hash = Telegram_User.remove("hash").getAsString();


    try {

        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");

        String[] t = Telegram_User.toString().replace("{","").replace("}","").replace("\":","=").replace(",","\n").replace("\"","").split("\n");

        sha256_HMAC.init(new SecretKeySpec(MessageDigest.getInstance("SHA-256").digest(BezouroBot.telegram.getBotToken().getBytes(StandardCharsets.UTF_8)),"SHA256"));


        Arrays.sort(t);

        StringBuilder i = new StringBuilder();

        boolean First = true;


        for (String s : t) if(First){ First = false; i = new StringBuilder(s);} else i.append("\n").append(s);


        return Hex.encodeHexString(sha256_HMAC.doFinal(i.toString().getBytes())).equals(hash);


    } catch (NoSuchAlgorithmException | InvalidKeyException e) {

        e.printStackTrace();

        return false;

    }


}


查看完整回答
反对 回复 2023-06-21
?
慕码人2483693

TA贡献1860条经验 获得超9个赞

这是我的工具


// define your token to a variable

private final String TELEGRAM_TOKEN = ""


@PostMapping("auth/telegram")

public ResponseEntity<Object> telegramAuth(@RequestBody Map<String, Object> request) {

    String hash = (String) request.get("hash");

    request.remove("hash");


    // Prepare the string

    String str = request.entrySet().stream()

            .sorted((a, b) -> a.getKey().compareToIgnoreCase(b.getKey()))

            .map(kvp -> kvp.getKey() + "=" + kvp.getValue())

            .collect(Collectors.joining("\n"));


    try {

        SecretKeySpec sk = new SecretKeySpec(

                // Get SHA 256 from telegram token

                MessageDigest.getInstance("SHA-256").digest(TELEGRAM_TOKEN.getBytes(StandardCharsets.UTF_8)

                ), "HmacSHA256");

        Mac mac = Mac.getInstance("HmacSHA256");

        mac.init(sk);


        byte[] result = mac.doFinal(str.getBytes(StandardCharsets.UTF_8));


        // Convert the result to hex string

        // Like https://stackoverflow.com/questions/9655181

        String resultStr = ByteBufUtil.bytesToHex(result);


        // Compare the result with the hash from body

        if(hash.compareToIgnoreCase(resultStr) == 0) {


            // Do other things like create a user and JWT token

            return ResponseEntity.ok("ok");

        } else {

            return ResponseEntity.status(HttpStatus.FORBIDDEN).body(

                    new MessageResponse("Login info hash mismatch")

            );

        }

    } catch (Exception e) {

        logger.error(e.getMessage(), e);

        return ResponseEntity.status(HttpStatus.FORBIDDEN).body(

                new MessageResponse("Server error while authenticating")

        );

    }

}



查看完整回答
反对 回复 2023-06-21
  • 2 回答
  • 0 关注
  • 163 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信