Home
avatar

lnblxj

让微信主动跳转到浏览器

流程

通过请求头判断是否是微信—>返回doc文档响应头诱骗 —> 弹出跳转浏览器弹窗

Node.js(Express) 实现

// 首页 - 微信跳转逻辑
router.get('/', function(req, res) {
  var userAgent = req.headers['user-agent'] || '';
  var clientIP = req.headers['x-forwarded-for'] || req.connection.remoteAddress || 'unknown';
  
  if (isWeChat(userAgent)) {
    console.log('WeChat access from', clientIP, '- triggering browser redirect');
    // 微信环境:发送文件头触发下载,唤起系统浏览器
    res.setHeader('Content-Description', 'File Transfer');
    res.setHeader('Content-Type', 'application/octet-stream');
    res.setHeader('Content-Disposition', 'attachment; filename="jump.doc"');
    res.setHeader('Expires', '0');
    res.setHeader('Cache-Control', 'must-revalidate');
    res.setHeader('Pragma', 'public');
    res.send('redirect');
  } else {
    console.log('Browser access from', clientIP, '- redirecting to download page');
    // 非微信环境:重定向到下载页面
    res.redirect('/download');
  }
});

function isWeChat(userAgent) {
  return userAgent && userAgent.toLowerCase().indexOf('micromessenger') !== -1;
}

Java实现

@RestController
@RequestMapping("/")
@Slf4j
public class HomeController {

    @GetMapping
    public ResponseEntity<?> home(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        String clientIp = IpUtils.getClientIp(request);

        if (UserAgentUtils.isWeChat(userAgent)) {
            log.info("WeChat access from {} - triggering browser redirect", clientIp);
            return buildWeChatRedirectResponse();
        } else {
            log.info("Browser access from {} - redirecting to download page", clientIp);
            HttpHeaders headers = new HttpHeaders();
            headers.setLocation(URI.create("/download"));
            return new ResponseEntity<>(headers, HttpStatus.FOUND);
        }
    }

    private ResponseEntity<byte[]> buildWeChatRedirectResponse() {
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_DESCRIPTION, "File Transfer");
        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
        headers.add(
                HttpHeaders.CONTENT_DISPOSITION,
                "attachment; filename=\"jump.doc\""
        );
        headers.add(HttpHeaders.EXPIRES, "0");
        headers.add(HttpHeaders.CACHE_CONTROL, "must-revalidate");
        headers.add(HttpHeaders.PRAGMA, "public");

        byte[] body = "redirect".getBytes(StandardCharsets.UTF_8);
        return new ResponseEntity<>(body, headers, HttpStatus.OK);
    }
}
后端 微信