Java实现微信小程序文本安全内容检测

前言

项目修改优化中遇到对输入的昵称做敏感词检测过滤,查找资料发现微信小程序官方文档中有提供相应的服务端接口。先将实现做下记录。

一、微信开发接口描述

security.msgSecCheck :检查一段文本是否含有违法违规内容。
auth.getAccessToken:获取小程序全局唯一后台接口调用凭据(access_token)

1.security.msgSecCheck:文本安全内容检测接口

这是接口基于HTTPS协议。开发者服务器可以调用此接口校验一段文本是否含有敏感信息。

应用场景举例:
户个人资料违规文字检测;媒体新闻类用户发表文章,评论内容检测;游戏类用户编辑上传的素材(如答题类小游戏用户上传的问题及答案)检测等。

频率限制:
单个 appId 调用上限为 4000 次/分钟,2,000,000 次/天* *服务市场:**通过服务市场使用可以有更多的能力,文档详情

调用方式:

  • HTTPS 调用
  • 云调用
  • 增量调用(加强版)

本文主要讲解HTTPS 调用 方式

HTTPS 调用请求地址:

POST https://api.weixin.qq.com/wxa/msg_sec_check?access_token=ACCESS_TOKEN

请求参数

参数类型必填说明
access_tokenstring接口调用凭证
contentString要检测的文本内容,长度不超过500K字节

在这里插入图片描述

2.auth.getAccessToken:获取access_token

想要调用 上一步的请求地址,需要先获取 access_token(小程序全局唯一后台接口调用凭据)。
官方文档

请求地址:

GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

在请求之前,需要appid、secret这两个参数,都需要从微信小程序平台获取。

access_token的注意事项:
在这里插入图片描述

二、Java代码实现

要调用**文本安全内容检测接口**,首先要获取access_token

1.Java获取微信小程序接口调用凭证access_token

	/**
	 * 调用微信开放接口 获取小程序全局唯一后台接口调用凭据(access_token)
	 * @return
	 */
	public static String getAccessToken(){
		//APPID,APPSECRET修改为你个人的
		String APPID=App.APPID;
		String APPSECRET=App.APP_SECRET;
		String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+APPID+"&secret="+APPSECRET;
		HttpRequestUtil hru = new HttpRequestUtil();
		JSONObject json = hru.sendUrlGet(accessTokenUrl);
		String access_token = json.getString("access_token");
		if(Tool.isEmpty(access_token)){
			access_token="";
		}
		
		System.out.println("json:"+json.toString());
				
		return access_token;
	}

获取微信AccessToken,保存在redis中,过期后重新获取:

	/**
	 * 获取小程序全局唯一后台接口调用凭据(access_token)
	 * @return
	 */
	public static String getWxAccessToken(){
		//从redis缓存中获取AccessToken,有且未过期,直接返回;否则重新获取
		String accessToken =RedisManager.get("accessToken");
		if(Tool.notEmpty(accessToken)){
			return accessToken;
		}
		//重新获取accessToken,并存入redis
		String newToken = getAccessToken();
		//存入redis
		RedisManager.set("accessToken", newToken, 7000);
		return newToken;
	}

RedisManager为自定义的redis工具类,里面包含redis初始化方法和各种存取方法。

2.Java调用微信开放接口msgSecCheck检测文字内容

添加httpclient maven依赖

<!--调用 http 请求-->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.3</version>
</dependency>

代码实现:

	 /**
     * 调用微信开放接口msgSecCheck检测文字内容
     * 频率限制:单个appid调用上限为2000次/分钟,1,000,000次/天
     * @param msg 要检测的文字内容
     * @param accessToken 小程序全局唯一后台接口调用凭据
     * @return true:含敏感信息   false:正常
     */
    public static Boolean checkMsg(String msg, String accessToken){
        String url = "https://api.weixin.qq.com/wxa/msg_sec_check?access_token=" + accessToken;
        //创建客户端
        HttpClient httpclient = HttpClients.createDefault();
        //创建一个post请求
        HttpPost request = new HttpPost(url);
        //设置响应头
        request.setHeader("Content-Type", "application/json;charset=UTF-8");
        //通过fastJson设置json数据
        JSONObject postData = new JSONObject();
        //设置要检测的内容
        postData.put("content", msg);
        String jsonString = postData.toString();
        request.setEntity(new StringEntity(jsonString,"utf-8"));
         由客户端执行(发送)请求
        try {
            HttpResponse response = httpclient.execute(request);
            // 从响应模型中获取响应实体
            HttpEntity entity = response.getEntity();
            //得到响应结果
            String result = EntityUtils.toString(entity,"utf-8");
            //打印检测结果
            System.out.println("检测结果:"+result);
            //将响应结果变成json
            JSONObject resultJsonObject = JSONObject.parseObject(result);
            
            String errcode =resultJsonObject.getString("errcode");
            if(errcode.equals("87014")){//当content内含有敏感信息,则返回87014
            	return true;
            }
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

HttpRequestUtil:HTTP请求类

package com.njpp.wxxcx.util;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.Map;

import com.alibaba.fastjson.JSONObject;

/**
 * 用于发送HTTP请求-----返回值为json
 * @author JH
 * @date 2018年9月21日 16:09:36
 */
public class HttpRequestUtil {
	/**
	 * 调用接口查询数据 get
	 * 
	 * @param action
	 * @param type
	 * @return
	 * @throws MalformedURLException
	 */
	public JSONObject sendUrlGet(String action) {
		URL url;
		JSONObject json = null;
		try {
			url = new URL(action.toString());
			HttpURLConnection http = (HttpURLConnection) url.openConnection();
			// 设定请求的方法为"POST",默认是GET 
			http.setRequestMethod("GET");
			// 设定传送的内容类型是可序列化的java对象 
			// (如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException) 
			http.setRequestProperty("Content-Type",
					"application/x-www-form-urlencoded");
			// 设置是否向httpUrlConnection输出,因为这个是post请求,参数要放在 
			// http正文内,因此需要设为true, 默认情况下是false; 
			http.setDoOutput(false); 
			// 设置是否从httpUrlConnection读入,默认情况下是true; 
			http.setDoInput(true);
			InputStream is = http.getInputStream();
			int size = is.available();
			byte[] buf = new byte[size];
			is.read(buf);
			String resp = new String(buf, "UTF-8");
			json = JSONObject.parseObject(resp);
		} catch (MalformedURLException e) {
			e.printStackTrace();
			return json;
		} catch (ProtocolException e) {
			e.printStackTrace();
			return json;
		} catch (IOException e) {
			e.printStackTrace();
			return json;
		}
		return json;
	}

	/**
	 * 调用接口查询数据 post
	 * 
	 * @param action
	 * @param type
	 * @return
	 * @throws MalformedURLException
	 */
	public JSONObject sendUrlPost(String action, Map inMap) {
		HttpURLConnection conn = null;
		InputStream is = null;
		InputStreamReader reader = null;
		BufferedReader br = null;
		String str = "";
		try {
			URL url = new URL(action);
			conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("POST");
			conn.setDoOutput(true);// 默认为false的,所以需要设置
			conn.setUseCaches(false);
			conn.setRequestProperty("Content-Type",
					"application/x-www-form-urlencoded");
			conn.connect();
			// 开始访问
			StringBuilder postData = new StringBuilder();
			OutputStream outStream = conn.getOutputStream();
			DataOutputStream out = new DataOutputStream(outStream);
			JSONObject jso = new JSONObject();
			//把参数转换成json字符串
			String params = jso.toJSONString(inMap);
			//传输参数
			out.writeBytes(params);
			out.close();

			is = conn.getInputStream();
			reader = new InputStreamReader(is, "UTF-8");
			br = new BufferedReader(reader);
			String readLine = "";
			while ((readLine = br.readLine()) != null) {
				str += readLine + "\n";
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				if (br != null) {
					br.close();
				}
				if (conn != null) {
					conn.disconnect();
				}
			} catch (Exception e1) {
				e1.printStackTrace();
			}
		}
		return JSONObject.parseObject(str);
	}
	
	
	
	/**
	 * 从网络Url中下载文件
	 * @param urlStr
	 * @param fileName
	 * @param savePath
	 * @throws IOException
	 */
	public static void  downLoadFromUrl(String urlStr,String fileName,String savePath) throws IOException{
	    URL url = new URL(urlStr);
	    HttpURLConnection conn = (HttpURLConnection)url.openConnection();
	    //设置超时间为3秒
	    conn.setConnectTimeout(8*1000);
	    //防止屏蔽程序抓取而返回403错误
	    conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

	    //得到输入流
	    InputStream inputStream = conn.getInputStream();
	    //获取自己数组
	    byte[] getData = readInputStream(inputStream);

	    //文件保存位置
	    File saveDir = new File(savePath);
	    if(!saveDir.exists()){
	        saveDir.mkdir();
	    }
	    File file = new File(saveDir+File.separator+fileName);
	    FileOutputStream fos = new FileOutputStream(file);
	    fos.write(getData);
	    if(fos!=null){
	        fos.close();
	    }
	    if(inputStream!=null){
	        inputStream.close();
	    }


	    System.out.println("info:"+url+" download success");

	}
	/**
	 * 从输入流中获取字节数组
	 * @param inputStream
	 * @return
	 * @throws IOException
	 */
	public static  byte[] readInputStream(InputStream inputStream) throws IOException {
	    byte[] buffer = new byte[1024];
	    int len = 0;
	    ByteArrayOutputStream bos = new ByteArrayOutputStream();
	    while((len = inputStream.read(buffer)) != -1) {
	        bos.write(buffer, 0, len);
	    }
	    bos.close();
	    return bos.toByteArray();
	}   
}

完整代码:

package com.njpp.wxxcx.util;

import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import com.alibaba.fastjson.JSONObject;
import com.njpp.wxxcx.core.common.App;
import com.njpp.wxxcx.core.common.Tool;
import com.njpp.wxxcx.util.redis.RedisManager;

/**
 * 微信小程序 工具类
 * @author Administrator
 *
 */
public class WxUtil {
	
	/**
	 * 监测文本内容是否含有敏感信息
	 */
	public static Boolean checkText(String msg){
		//获取token
		String token = getWxAccessToken();
		//返回监测结果
		return checkMsg(msg, token);
	}
	
	/**
	 * 获取小程序全局唯一后台接口调用凭据(access_token)
	 * @return
	 */
	public static String getWxAccessToken(){
		//从redis缓存中获取AccessToken,有且为过期,直接返回;否则重新获取
		String accessToken =RedisManager.get("accessToken");
		if(Tool.notEmpty(accessToken)){
			return accessToken;
		}
		//重新获取accessToken,并存入redis
		String newToken = getAccessToken();
		//存入redis
		RedisManager.set("accessToken", newToken, 7000);
		return newToken;
	}
	/**
	 * 调用微信开放接口 获取小程序全局唯一后台接口调用凭据(access_token)
	 * @return
	 */
	public static String getAccessToken(){
		
		String APPID=App.APPID;
		String APPSECRET=App.APP_SECRET;
//		String APPID="wxc0fdedb12b148d11";
//		String APPSECRET="83a90fa477b6929d328ec47ca193f666";
		String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+APPID+"&secret="+APPSECRET;
		HttpRequestUtil hru = new HttpRequestUtil();
		JSONObject json = hru.sendUrlGet(accessTokenUrl);
		String access_token = json.getString("access_token");
		if(Tool.isEmpty(access_token)){
			access_token="";
		}
		
		System.out.println("json:"+json.toString());
				
		return access_token;
	}
	
	 /**
     * 调用微信开放接口msgSecCheck检测文字内容
     * 频率限制:单个appid调用上限为2000次/分钟,1,000,000次/天
     * @param msg 要检测的文字内容
     * @param accessToken 小程序全局唯一后台接口调用凭据
     * @return true:含敏感信息   false:正常
     */
    public static Boolean checkMsg(String msg, String accessToken){
        String url = "https://api.weixin.qq.com/wxa/msg_sec_check?access_token=" + accessToken;
        //创建客户端
        HttpClient httpclient = HttpClients.createDefault();
        //创建一个post请求
        HttpPost request = new HttpPost(url);
        //设置响应头
        request.setHeader("Content-Type", "application/json;charset=UTF-8");
        //通过fastJson设置json数据
        JSONObject postData = new JSONObject();
        //设置要检测的内容
        postData.put("content", msg);
        String jsonString = postData.toString();
        request.setEntity(new StringEntity(jsonString,"utf-8"));
         由客户端执行(发送)请求
        try {
            HttpResponse response = httpclient.execute(request);
            // 从响应模型中获取响应实体
            HttpEntity entity = response.getEntity();
            //得到响应结果
            String result = EntityUtils.toString(entity,"utf-8");
            //打印检测结果
            System.out.println("检测结果:"+result);
            //将响应结果变成json
            JSONObject resultJsonObject = JSONObject.parseObject(result);
            
            String errcode =resultJsonObject.getString("errcode");
            if(errcode.equals("87014")){//当content内含有敏感信息,则返回87014
            	return true;
            }
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
    
    /**
     * 检测图片是否含有违法违规内容
     * 频率限制:单个appid调用上限为1000次/分钟,100,000次/天
     * @param inputStream 图片文件  流multipartFile.getInputStream()
     * @param contentType 图片文件类型  multipartFile.getContentType()
     * @return true:含敏感信息   false:正常
     * media 要检测的图片文件,格式支持PNGJPEGJPGGIF, 像素不超过750x1334
     */
    public static Boolean checkImg(InputStream inputStream, String contentType){
    	 try {
    		 //获取token  小程序全局唯一后台接口调用凭据
    		 String accessToken = getWxAccessToken();
    		 
			 CloseableHttpClient httpclient = HttpClients.createDefault();
			 CloseableHttpResponse response = null;
			 HttpPost request = new HttpPost("https://api.weixin.qq.com/wxa/img_sec_check?access_token=" + accessToken);
			 request.addHeader("Content-Type", "application/octet-stream");
			 byte[] byt = new byte[inputStream.available()];
			 inputStream.read(byt);
			 request.setEntity(new ByteArrayEntity(byt, ContentType.create(contentType)));
			 response = httpclient.execute(request);
			 HttpEntity httpEntity = response.getEntity();
			 String result = EntityUtils.toString(httpEntity, "UTF-8");// 转成string
			 JSONObject jso = JSONObject.parseObject(result);
			 
			 String errcode = jso.getString("errcode");
			 if(errcode.equals("87014")){//当content内含有敏感信息,则返回87014
	            return true;
	         }
			 return false;
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
    }
	public static void main(String[] args) {
		String access_token="36_jocRV09Bx3lck-xxyYWvQWdv-5otrobLiwil3i-cvELcwnfnl-dUT2O2fiMyQbAYhYLBBE5kcPkRERfb079aeuT7POHmWyJPcCVoCJmTvq1J5__cBZl9Ayahmvxv_EDIP18lgYfiNZi7TZKmVTKfAIAECT";
		String content="特3456书yuuo莞6543李zxcz蒜7782法fgnv级
完2347全dfji试3726测asad感3847知qwez到";
		
		checkMsg(content, access_token);
	}
}

参考资料:
内容安全接口开发文档

文本审核API收集

https://blog.csdn.net/qq_38765867/article/details/106366970


版权声明:本文为qq_26383975原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。