MiraiForum

    • 注册
    • 登录
    • 搜索
    • 热门
    • 最新
    • 未解决
    • 标签
    • 群组
    • 友情链接

    Spring Boot maven工程如何实现扫码登录?

    开发交流
    6
    15
    1290
    正在加载更多帖子
    • 从旧到新
    • 从新到旧
    • 最多赞同
    回复
    • 在新帖中回复
    登录后回复
    此主题已被删除。只有拥有主题管理权限的用户可以查看。
    • 2
      2446694 最后由 2446694 编辑

      问题出现

      以下是在工程里的相关配置
      newBotConfiguration方法会生成自己定义的配置
      我在登录的时候提示需要二维码登录
      0536152e-6f62-40ed-8274-ac6cdcdbd031-image.png
      我找到了mirai-login-solver-sakura插件,但我不知道在SpringBoot中如何使用它?
      18287a49-4e78-4c9b-9622-3befaf98e235-image.png fe7ce264-7b35-477e-b4b3-aa7fb4b3db15-image.png

      需求

      • 如何在SpringBoot工程中使用mirai-login-solver-sakura(mirai console插件)
      • 如何实现二维码登录 或 短信验证码登录?
      1 条回复 最后回复 回复 引用 0
      • J
        Jadlokin-Scarlet 最后由 编辑

        干脆用mirai-http-api得了(歪楼)

        1 条回复 最后回复 回复 引用 0
        • abc408880155
          abc408880155 最后由 编辑

          非程序员,医学生,我是这么写的代码,你可以参考,可扫码,可短信验证登陆,基于目前的2.15.0-M1: public static void login(Long botAccount, String botPassword) {
          Configuration config = ConfigManager.getConfig();

              ClassLoader loader = Thread.currentThread().getContextClassLoader();
              Thread.currentThread().setContextClassLoader(GlobalEventChannel.class.getClassLoader());
          
              boolean loginByQR = config.getBoolean("loginByQR");
              File workingDir = new File(ConfigManager.pluginDirectory, "bot");
          
              if(!workingDir.exists()) workingDir.mkdirs();
          
          
              BotFactory.BotConfigurationLambda botConfigurationLambda = botConfiguration -> {
                  botConfiguration.setWorkingDir(workingDir);
                  if (config.getBoolean("redirectBotLogToDirectory")) {
                      botConfiguration.redirectBotLogToDirectory();
                  }
                  if (config.getBoolean("noNetworkLog")) {
                      botConfiguration.noNetworkLog();
                  }
                  if (config.getBoolean("noBotLog")) {
                      botConfiguration.noBotLog();
                  }
                  botConfiguration.setProtocol(BotConfiguration.MiraiProtocol.valueOf(config.getString("bot-login-device")));
                  botConfiguration.setCacheDir(new File("cache"));
                  botConfiguration.fileBasedDeviceInfo();
                  File deviceFile = new File(botConfiguration.getWorkingDir(), "device.json");
                  if (deviceFile.exists()) {
                      botConfiguration.setDeviceInfo(bot1 -> DeviceInfo.from(deviceFile));
                  }
              };
          
              bot = loginByQR ? BotFactory.INSTANCE.newBot(botAccount, BotAuthorization.byQRCode(), botConfigurationLambda) :
                      BotFactory.INSTANCE.newBot(botAccount, botPassword, new BotConfiguration() {{
                          setWorkingDir(workingDir);
                          if (config.getBoolean("redirectBotLogToDirectory")) {
                              redirectBotLogToDirectory();
                          }
                          if (config.getBoolean("noNetworkLog")) {
                              noNetworkLog();
                          }
                          if (config.getBoolean("noBotLog")) {
                              noBotLog();
                          }
          
                          //FixProtocolVersion.update();
                          setProtocol(MiraiProtocol.valueOf(config.getString("bot-login-device")));
          
                          setCacheDir(new File("cache"));
                          fileBasedDeviceInfo();
                          File deviceFile = new File(getWorkingDir(), "device.json");
                          if (deviceFile.exists()) {
                              setDeviceInfo(bot1 -> DeviceInfo.from(deviceFile));
                          }
                      }});
          
              bot.login();
              Thread.currentThread().setContextClassLoader(loader);
          }
          
          2 2 条回复 最后回复 回复 引用 0
          • 2
            2446694 @abc408880155 最后由 编辑

            此回复已被删除!
            1 条回复 最后回复 回复 引用 0
            • 2
              2446694 @abc408880155 最后由 编辑

              @abc408880155 确实可以用,不过我项获取二维码图片发送到前端验证

              cssxsh 1 条回复 最后回复 回复 引用 0
              • abc408880155
                abc408880155 最后由 编辑

                不明白前端,我还只简单学了学Java,研究了下mirai给的说明。不过,它的二维码图片估计得看他的源码是怎么发出来的,复写下应该可以。你如果折腾明白了,麻烦转告我下

                1 条回复 最后回复 回复 引用 0
                • cssxsh
                  cssxsh @2446694 最后由 编辑

                  @2446694

                  你需要自定义一个登录解决器

                  https://github.com/mamoe/mirai/blob/dev/docs/Bots.md#覆盖登录解决器

                  abc408880155 1 条回复 最后回复 回复 引用 0
                  • abc408880155
                    abc408880155 @cssxsh 最后由 编辑

                    @cssxsh nice……之前一直没看到这个,谢啦

                    2 1 条回复 最后回复 回复 引用 0
                    • 2
                      2446694 @abc408880155 最后由 编辑

                      @abc408880155 createQRCodeLoginListener来获取二维码。

                      // 自定义LoginSolver
                      public class QqLoginSolver extends LoginSolver {
                          private Object verification(Long qq, Object request) {
                              QqSession qqSession = QqSessionManager.getQqSession(qq);
                              Object[] code = new Object[1];
                              CountDownLatch latch = new CountDownLatch(1); // 定义一个CountDownLatch对象,用于等待code[0]
                              qqSession.sendRequest(request, response -> {
                                  code[0] = response;
                                  latch.countDown();
                              });
                              try {
                                  latch.await(300000, TimeUnit.MILLISECONDS);
                              } catch (InterruptedException e) {
                                  // 错误处理
                              }
                              return code[0];
                          }
                      
                          @Nullable
                          @Override
                          public Object onSolvePicCaptcha(@NotNull Bot bot, @NotNull byte[] bytes, @NotNull Continuation<? super String> continuation) {
                              return verification(bot.getId(), bytes);
                          }
                      
                          @Nullable
                          @Override
                          public Object onSolveSliderCaptcha(@NotNull Bot bot, @NotNull String url, @NotNull Continuation<? super String> continuation) {
                              return verification(bot.getId(), url);
                          }
                      
                          @NotNull
                          @Override
                          public QRCodeLoginListener createQRCodeLoginListener(@NotNull Bot bot) {
                              return new QRCodeLoginListener() {
                      
                                  @Override
                                  public void onStateChanged(@NotNull Bot bot1, @NotNull State state) throws LoginFailedException {
                                      if (state.name().equals("TIMEOUT")) throw new RuntimeException("二维码已失效");
                                  }
                      
                                  @Override
                                  public void onFetchQRCode(@NotNull Bot bot1, @NotNull byte[] bytes) {
                                      QqSessionManager.getQqSession(bot1.getId()).sendRequest(bytes, null);
                                  }
                              };
                          }
                      }
                      
                      abc408880155 G 2 条回复 最后回复 回复 引用 0
                      • abc408880155
                        abc408880155 @2446694 最后由 编辑

                        @2446694 谢谢!

                        1 条回复 最后回复 回复 引用 0
                        • G
                          guizaipiao @2446694 最后由 编辑

                          @2446694
                          大佬,QqSession和 QqSessionManager我引不到,目前我只引了mirai-core-jvm这一个依赖,是不是还缺少了什么依赖?

                          2 1 条回复 最后回复 回复 引用 0
                          • 2
                            2446694 @guizaipiao 最后由 2446694 编辑

                            @guizaipiao

                            我使用的依赖是 mirai-core 这一个

                            以下是你提到的配置

                            QQSission

                            package com.session;
                            
                            import net.mamoe.mirai.Bot;
                            import net.mamoe.mirai.BotFactory;
                            import net.mamoe.mirai.auth.BotAuthorization;
                            import net.mamoe.mirai.contact.*;
                            import net.mamoe.mirai.event.EventChannel;
                            import net.mamoe.mirai.event.events.BotEvent;
                            import net.mamoe.mirai.utils.BotConfiguration;
                            import org.slf4j.Logger;
                            import org.slf4j.LoggerFactory;
                            
                            import java.util.function.Consumer;
                            
                            
                            /**
                             * ContactOrBot	Contact 和 Bot 的公共接口	2.0
                             * OtherClient	Bot 的其他客户端,如 “我的 iPad”,”我的电脑”	2.0
                             * Bot	机器人对象	2.0
                             * Contact	联系人对象,即所有的群,好友,陌生人,群成员等	2.0
                             * Group	群对象	2.0
                             * User	用户对象,即 “个人”. 包含好友,陌生人,群成员,临时会话用户	2.0
                             * Friend	好友对象	2.0
                             * Stranger	陌生人对象	2.0
                             * Member	群成员对象,属于一个 Group.	2.0
                             * NormalMember	普通群成员对象.	2.0
                             * AnonymousMember	匿名群成员对象.	2.0
                             */
                            
                            
                            public class QqSession {
                                private static final Logger logger = LoggerFactory.getLogger(QqSession.class);
                                private final Bot bot;
                                private final Consumer<Object> doRequest;
                                private Consumer<Object> doResponse;
                            
                                public QqSession(Long qq, String password, Consumer<Object> doRequest) {
                                    // 使用自定义配置
                                    BotConfiguration botConfiguration = new QqBotConfiguration(qq);
                                    // 定义属性
                                    this.bot = BotFactory.INSTANCE.newBot(qq, password, botConfiguration);
                                    // 验证信息处理
                                    this.doRequest = doRequest;
                                }
                            
                                public QqSession(Long qq, BotAuthorization credential, Consumer<Object> doRequest) {
                                    // 使用自定义配置
                                    BotConfiguration botConfiguration = new QqBotConfiguration(qq);
                                    // 二维码登录
                                    this.bot = BotFactory.INSTANCE.newBot(qq, credential, botConfiguration);
                                    // 验证信息处理
                                    this.doRequest = doRequest;
                                }
                            
                                public Bot getBot() {
                                    return this.bot;
                                }
                            
                                public boolean login() {
                                    this.bot.login();
                                    boolean isOnline = this.bot.isOnline();
                                    if (isOnline) logger.info(this.bot.getId() + " 登录成功");
                                    else logger.info(this.bot.getId() + " 登录失败");
                                    return isOnline;
                                }
                            
                                public boolean isOnline() {
                                    return this.bot.isOnline();
                                }
                            
                                public void close() {
                                    this.bot.close();
                                }
                            
                                public Long getQq() {
                                    return this.bot.getId();
                                }
                            
                                public ContactList<Friend> getFriends() {
                                    // 获取好友列表
                                    return this.bot.getFriends();
                                }
                            
                                public ContactList<Group> getGroups() {
                                    // 获取群列表
                                    return this.bot.getGroups();
                                }
                            
                                public Friend getFriend(Long id) {
                                    // 获取指定qq号好友
                                    return this.bot.getFriend(id);
                                }
                            
                                public Group getGroup(Long id) {
                                    // 根据群号获取群
                                    return this.bot.getGroup(id);
                                }
                            
                                public Stranger getStranger(Long id) {
                                    // 获取指定qq号陌生人
                                    return this.bot.getStranger(id);
                                }
                            
                                public ContactList<OtherClient> getOtherClients() {
                                    // 联系其他客户端
                                    return this.bot.getOtherClients();
                                }
                            
                                public EventChannel<BotEvent> getEventChannel() {
                                    return this.bot.getEventChannel();
                                }
                            
                                public void sendRequest(Object request, Consumer<Object> doResponse) {
                                    this.doResponse = doResponse;
                                    // 发送验证请求
                                    this.doRequest.accept(request);
                                }
                            
                            
                                public void sendResponse(String response) {
                                    // 响应验证码
                                    doResponse.accept(response);
                                }
                            }
                            
                            

                            QqSessionManager

                            package com.session;
                            
                            import net.mamoe.mirai.auth.BotAuthorization;
                            
                            import java.util.HashMap;
                            import java.util.Map;
                            import java.util.function.Consumer;
                            
                            public class QqSessionManager {
                                private static final Map<Long, QqSession> sessionMap = new HashMap<>();
                            
                                public static QqSession newQqSession(Long qq, Object credential, Consumer<Object> doRequest) {
                                    QqSession qqSession;
                                    if (credential instanceof BotAuthorization)
                                        qqSession = new QqSession(qq, (BotAuthorization) credential, doRequest);
                                    else if (credential instanceof String)
                                        qqSession = new QqSession(qq, (String) credential, doRequest);
                                    else throw new IllegalArgumentException("无效的credential");
                                    sessionMap.put(qq, qqSession);
                                    return qqSession;
                                }
                            
                                public static QqSession getQqSession(Long qq) {
                                    return sessionMap.get(qq);
                                }
                            
                                public static void removeQqSession(Long qq) {
                                    sessionMap.get(qq).close();
                                    sessionMap.remove(qq);
                                }
                            }
                            
                            
                            2 1 条回复 最后回复 回复 引用 0
                            • 2
                              2446694 @2446694 最后由 2446694 编辑

                              @2446694 在 Spring Boot maven工程如何实现扫码登录? 中说:

                              @guizaipiao

                              我使用的依赖是 mirai-core 这一个

                              以下是你提到的配置

                              QQSission

                              package com.session;
                              
                              import net.mamoe.mirai.Bot;
                              import net.mamoe.mirai.BotFactory;
                              import net.mamoe.mirai.auth.BotAuthorization;
                              import net.mamoe.mirai.contact.*;
                              import net.mamoe.mirai.event.EventChannel;
                              import net.mamoe.mirai.event.events.BotEvent;
                              import net.mamoe.mirai.utils.BotConfiguration;
                              import org.slf4j.Logger;
                              import org.slf4j.LoggerFactory;
                              
                              import java.util.function.Consumer;
                              
                              
                              /**
                               * ContactOrBot	Contact 和 Bot 的公共接口	2.0
                               * OtherClient	Bot 的其他客户端,如 “我的 iPad”,”我的电脑”	2.0
                               * Bot	机器人对象	2.0
                               * Contact	联系人对象,即所有的群,好友,陌生人,群成员等	2.0
                               * Group	群对象	2.0
                               * User	用户对象,即 “个人”. 包含好友,陌生人,群成员,临时会话用户	2.0
                               * Friend	好友对象	2.0
                               * Stranger	陌生人对象	2.0
                               * Member	群成员对象,属于一个 Group.	2.0
                               * NormalMember	普通群成员对象.	2.0
                               * AnonymousMember	匿名群成员对象.	2.0
                               */
                              
                              
                              public class QqSession {
                                  private static final Logger logger = LoggerFactory.getLogger(QqSession.class);
                                  private final Bot bot;
                                  private final Consumer<Object> doRequest;
                                  private Consumer<Object> doResponse;
                              
                                  public QqSession(Long qq, String password, Consumer<Object> doRequest) {
                                      // 使用自定义配置
                                      BotConfiguration botConfiguration = new QqBotConfiguration(qq);
                                      // 定义属性
                                      this.bot = BotFactory.INSTANCE.newBot(qq, password, botConfiguration);
                                      // 验证信息处理
                                      this.doRequest = doRequest;
                                  }
                              
                                  public QqSession(Long qq, BotAuthorization credential, Consumer<Object> doRequest) {
                                      // 使用自定义配置
                                      BotConfiguration botConfiguration = new QqBotConfiguration(qq);
                                      // 二维码登录
                                      this.bot = BotFactory.INSTANCE.newBot(qq, credential, botConfiguration);
                                      // 验证信息处理
                                      this.doRequest = doRequest;
                                  }
                              
                                  public Bot getBot() {
                                      return this.bot;
                                  }
                              
                                  public boolean login() {
                                      this.bot.login();
                                      boolean isOnline = this.bot.isOnline();
                                      if (isOnline) logger.info(this.bot.getId() + " 登录成功");
                                      else logger.info(this.bot.getId() + " 登录失败");
                                      return isOnline;
                                  }
                              
                                  public boolean isOnline() {
                                      return this.bot.isOnline();
                                  }
                              
                                  public void close() {
                                      this.bot.close();
                                  }
                              
                                  public Long getQq() {
                                      return this.bot.getId();
                                  }
                              
                                  public ContactList<Friend> getFriends() {
                                      // 获取好友列表
                                      return this.bot.getFriends();
                                  }
                              
                                  public ContactList<Group> getGroups() {
                                      // 获取群列表
                                      return this.bot.getGroups();
                                  }
                              
                                  public Friend getFriend(Long id) {
                                      // 获取指定qq号好友
                                      return this.bot.getFriend(id);
                                  }
                              
                                  public Group getGroup(Long id) {
                                      // 根据群号获取群
                                      return this.bot.getGroup(id);
                                  }
                              
                                  public Stranger getStranger(Long id) {
                                      // 获取指定qq号陌生人
                                      return this.bot.getStranger(id);
                                  }
                              
                                  public ContactList<OtherClient> getOtherClients() {
                                      // 联系其他客户端
                                      return this.bot.getOtherClients();
                                  }
                              
                                  public EventChannel<BotEvent> getEventChannel() {
                                      return this.bot.getEventChannel();
                                  }
                              
                                  public void sendRequest(Object request, Consumer<Object> doResponse) {
                                      this.doResponse = doResponse;
                                      // 发送验证请求
                                      this.doRequest.accept(request);
                                  }
                              
                              
                                  public void sendResponse(String response) {
                                      // 响应验证码
                                      doResponse.accept(response);
                                  }
                              }
                              
                              

                              QqSessionManager

                              package com.session;
                              
                              import net.mamoe.mirai.auth.BotAuthorization;
                              
                              import java.util.HashMap;
                              import java.util.Map;
                              import java.util.function.Consumer;
                              
                              public class QqSessionManager {
                                  private static final Map<Long, QqSession> sessionMap = new HashMap<>();
                              
                                  public static QqSession newQqSession(Long qq, Object credential, Consumer<Object> doRequest) {
                                      QqSession qqSession;
                                      if (credential instanceof BotAuthorization)
                                          qqSession = new QqSession(qq, (BotAuthorization) credential, doRequest);
                                      else if (credential instanceof String)
                                          qqSession = new QqSession(qq, (String) credential, doRequest);
                                      else throw new IllegalArgumentException("无效的credential");
                                      sessionMap.put(qq, qqSession);
                                      return qqSession;
                                  }
                              
                                  public static QqSession getQqSession(Long qq) {
                                      return sessionMap.get(qq);
                                  }
                              
                                  public static void removeQqSession(Long qq) {
                                      sessionMap.get(qq).close();
                                      sessionMap.remove(qq);
                                  }
                              }
                              
                              

                              Controller层实现

                              @PostMapping("/login")
                                  public Result<Object> request(@RequestParam("qq") Long qq, @RequestParam(value = "pwd", required = false) String pwd) throws InterruptedException {
                                      Result<Object> result = new Result<>(); // 将url信息设置到result中
                                      QqSession[] qqSession = new QqSession[]{QqSessionManager.getQqSession(qq)};
                                      if (qqSession[0] == null || !qqSession[0].isOnline()) {
                                          CountDownLatch latch = new CountDownLatch(1); // 定义一个CountDownLatch对象,用于等待result.setData
                                          new Thread(() -> {
                                              if (pwd == null) {
                                                  result.setCode(220);
                                                  qqSession[0] = QqSessionManager.newQqSession(qq, BotAuthorization.byQRCode(), object -> {
                                                      byte[] bytes = (byte[]) object;
                                                      String base64Image = "data:image/png;base64," + Base64.getEncoder().encodeToString(bytes);
                                                      result.setData(base64Image, "请扫码");  // 将图片设置到result中
                                                      latch.countDown();
                                                  });
                                              } else {
                                                  result.setCode(210);
                                                  qqSession[0] = QqSessionManager.newQqSession(qq, pwd, object -> {
                                                      if (object instanceof byte[]) {
                                                          byte[] bytes = (byte[]) object;
                                                          String base64Image = "data:image/png;base64," + Base64.getEncoder().encodeToString(bytes);
                                                          result.setData(base64Image, "请处理验证码");  // 将图片设置到result中
                                                      } else result.setData(object, "请处理url"); // 将url信息设置到result中
                                                      latch.countDown();
                                                  });
                                              }
                                              result.setCode(200).setData(qqSession[0].login(),"登录成功");
                                              latch.countDown();
                                          }).start();
                                          latch.await(10000, TimeUnit.MILLISECONDS);  // 调用CountDownLatch对象的await方法等待url信息被设置
                                      } else {
                                          result.setCode(200).setData(qqSession[0].isOnline(), "已经登录过了");
                                      }
                                      return result; // 返回result对象给前端
                                  }
                              

                              Result类

                              package com.domain;
                              
                              import java.util.HashMap;
                              import java.util.Map;
                              
                              public class Result<T> {
                                  static {
                                      Result.codeMap = new HashMap<>();
                                      Result.codeMap.put(100, "查询失败,没有找到相关数据");
                                      Result.codeMap.put(110, "添加失败,无法添加该数据");
                                      Result.codeMap.put(120, "删除失败,相关数据不存在");
                                      Result.codeMap.put(130, "修改失败,相关数据不存在");
                              
                                      Result.codeMap.put(200, "登录失败");
                                      Result.codeMap.put(210, "验证码失效");
                                      Result.codeMap.put(220, "二维码失效");
                                      Result.codeMap.put(230, "短信验证失效");
                                      Result.codeMap.put(290, "登出失败");
                              
                                      Result.codeMap.put(900, "请求数据有误");
                                      Result.codeMap.put(910, "系统繁忙,请稍后再试");
                                      Result.codeMap.put(990, "发生未知的错误,暂时无法处理");
                                  }
                              
                                  private static Map<Integer, String> codeMap;
                              
                                  private int code;
                                  private String msg;
                                  private T data;
                              
                                  public Result() {
                                  }
                              
                                  public Result(int code) {
                                      // 设置十位数上的值
                                      this.code = code;
                                      this.msg = codeMap.get(code);
                                  }
                              
                                  public int getCode() {
                                      return code;
                                  }
                              
                                  public Result<T> setCode(int code) {
                                      this.code = code;
                                      this.msg = codeMap.get(code);
                                      return this;
                                  }
                              
                                  public String getMsg() {
                                      return msg;
                                  }
                              
                                  public Result<T> setErrorMsg(String errorMsg) {
                                      // 如果代码为0,则表示异常或失败,设置错误信息
                                      if (this.code % 10 == 0) this.msg = errorMsg;
                                      return this;
                                  }
                              
                                  public T getData() {
                                      return data;
                                  }
                              
                                  public Result<T> setData(T data) {
                                      // 改变个位数上的值
                                      if (notNone(data) && this.code / 100 != 9) {
                                          this.code = this.code / 10 * 10 + 1;
                                          this.msg = "操作成功";
                                      }
                                      this.data = data;
                                      return this;
                                  }
                              
                                  public Result<T> setData(T data, String msg) {
                                      // 改变个位数上的值
                                      if (notNone(data) && this.code / 100 != 9) {
                                          this.code = this.code / 10 * 10 + 1;
                                          this.msg = msg;
                                      }
                                      this.data = data;
                                      return this;
                                  }
                              
                                  private boolean notNone(Object value) {
                                      // Character(char(\u0000)) 会被 instanceof Number == 0 处理
                                      return value instanceof Boolean ? (Boolean) value : value instanceof Number ? value != (Number) 0 : value instanceof String ? value != "" : value != null;
                                  }
                              
                                  @Override
                                  public String toString() {
                                      return "Result{code=" + code + ", msg=" + msg + ", data=" + data + '}';
                                  }
                              }
                              
                              
                              G 1 条回复 最后回复 回复 引用 0
                              • Referenced by  2 2446694 
                              • G
                                guizaipiao @2446694 最后由 编辑

                                @2446694
                                成功登录了,感谢大佬。

                                1 条回复 最后回复 回复 引用 0
                                • 1
                                  1guankui 最后由 编辑

                                  有没有simbot.boot框架加扫码的方法呢?

                                  1 条回复 最后回复 回复 引用 0
                                  • 1 / 1
                                  • First post
                                    Last post
                                  Powered by Mamoe Technologies & NodeBB | 友情链接 | 服务监控 | Contact