0%

Vue的拦截器和第三方微信登录的使用总结

一. axios拦截器

1. axios携带token

//main.js
//======================axios的前置拦截器【拦截调用后端的请求====================//
axios.interceptors.request.use(res=>{
  let token = localStorage.getItem("token");
  if(token){
    res.headers["token"] = token;
  }
  return res;
},error => {
  Promise.reject(error)
})
//======================axios的前置拦截器【拦截调用后端的请求】====================//

2. 后端拦截器

@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
        //1.获取token
        String token = req.getHeader("token");
        //3.如果有token,通过token获取redis的登录信息
        if (token != null) {
            String loginInfo = stringRedisTemplate.opsForValue().get(Constants.LOGIN_TOKEN + token); // LoginInfo对象
            if (loginInfo != null) {//登录成功,而且没有过期
                //5.如果登录信息不为null - 放行 + 刷新过期时间[重新添加到redis]
                stringRedisTemplate.opsForValue().set(token, loginInfo, 30, TimeUnit.MINUTES);
                return true;
            }
        }
        //2.判断token,如果为null - 直接拦截 响应前端 - 跳转到登录页面
        //4.如果登录信息为null - 过期了 直接拦截 响应前端 - 跳转到登录页面

        //跳转到登录页面 - 后端跳不了,因为后端项目没有页面 - 放在前端跳转
        //告诉浏览器我要给你响应一个json数据,编码集为utf-8
        resp.setContentType("application/json;charset=UTF-8");
        resp.getWriter().println("{\"success\":false,\"message\":\"noLogin\"}");
        return false;
    }
 }

3. 处理拦截器响应

//main.js
//======================axios的后置拦截器【处理后台登录拦截的结果】====================//
axios.interceptors.response.use(res => {
    //后端响应的是没有登录的信息
    if (false === res.data.success && "noLogin" === res.data.message) {
        localStorage.removeItem("token");
        localStorage.removeItem("logininfo");
        router.push({path: '/login'});
      }
      return res;
},error => {
      Promise.reject(error)
})
//======================axios的后置拦截器【处理后台登录拦截的结果】====================//

4. 路由拦截器

//======================路由的前端拦截器【拦截不到后端的请求】====================//
//注释掉登陆拦截:判断session中有没有user对象并且路径不是login就调转到登录页面
router.beforeEach((to, from, next) => {
    if (to.path == '/login' || to.path == "/register") {
        next();//放行
      }else{
        let logininfo = localStorage.getItem('logininfo');
        if (logininfo) {
              next();
        } else {
              next({path: '/login'});//跳转到login
        }
      }
})

5. 前端登录代码

    handleSubmit2(ev) {
      //表单校验:所有表单项校验成功才返回为true - 才能发送请求
      this.$refs.ruleForm2.validate((valid) => {
        if (valid) {
          this.logining = true; //显示加载框或忙等框
          this.$http.post("/login/account", this.ruleForm2).then(res => {
            if (res.data.success) {//登录成功
              //1.显示成功信息
              this.$message({
                message: "登录成功",
                type: 'success'
              });
              let {token, loginInfo} = res.data.data
              localStorage.setItem("token", token)
              localStorage.setItem("logininfo", JSON.stringify(logininfo))
              console.log(res.data);
              //跳转到后台首页
              this.$router.push({path: '/echarts'});
            } else {//登录失败
              this.$message.error(res.data.msg);
            }
            this.logining = false; //关闭加载框或忙等框
          }).catch(res => {
            this.$message.error("系统繁忙,请稍后重试!!!【400,404】")
            this.logining = false; //关闭加载框或忙等框
          })
        } else {
          console.log('表单校验失败!!!');
          return false;
        }
      });
    }

二. 第三方登录概述

1. 什么是第三方登录

三方登录指的是基于用户在主流平台【微信,支付宝,QQ】上已有的账号来快速完成己方应用的登录或者注册的功能。而这里的主流平台,一般是已经拥有大量用户的平台,国外的比如Facebook,Twitter等,国内的比如微博、微信、QQ等。 第三方登录的目的是使用用户在其他平台上频繁使用的账号,来快速登内录己方产品,也可以实现不注册就能登录,好处就是登录比较快捷,无需注册。

2. 优缺点

  • 优点:这些系统有很大的用户群体,可以扩大客户群,引流。不需要记录账号密码,不担心忘记,直接扫描登录,体验度高。简单快捷,无需注册就可以直接登录
  • 缺点:要交钱【网站运营商向微信运营商缴费】

三. 三方登录协议

1. OAuth2.0

OAuth协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是OAUTH的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAuth是安全的。OAuth是Open Authorization的简写,目前的版本是2.0版.

https://oauth.net/2/

例如:使用微信登录,并不会获取到微信的账号密码,只需要同意授权即可。如果我们的项目被攻破了,那就知道了用户的微信账号,然后用户的微信就危险了。小平台或小公司的系统很容易被攻击甚至被攻破

2. 运行流程

  1. 获取用户授权
  2. 得到用户授权获取令牌
  3. 使用令牌访问受限资源

(A)用户打开客户端以后,客户端要求用户给予授权。

(B)用户同意给予客户端授权。

(C)客户端使用上一步获得的授权,向认证服务器申请令牌。

(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。

(E)客户端使用令牌,向资源服务器申请获取资源。

(F)资源服务器确认令牌无误,同意向客户端开放资源。

上述六个步骤中,B是关键,即用户怎样才能给客户端授权。有了这个授权以后,客户端就可以获取令牌,进而凭借令牌获取资源

四. 微信登录概述

  1. 开发网址:https://open.weixin.qq.com/
  2. 自己的网站可以接入网站应用开发,为用户提供了微信登录功能,降低了注册门槛,并可在用户授权后,获取用户基本信息,包括头像、昵称、性别、地区。出于安全考虑,网站应用的微信登录,需通过微信扫描二维码来实现
  3. 注册账号:要想接入微信的登录功能,首先需要在微信开发平台进行用户的注册,同时需要认证为开发者,再创建网站应用,等待微信审批,审批过后,就可以使用相关功能
  4. 开发者认证:认证一次300人民币。 以后要做第三方登录
  5. 微信登陆功能官网教程网址:https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html

五. 微信登录实现

1. 三个请求

  • 微信登录一共发送三个请求:
    1. 授权请求 - a标签链接过去就OK,获取code
    2. 使用授权码codeappid和SECRET获取令牌token,返回tokenopenid - 后端使用Httpclient发送请求
    3. 如果微信用户没有绑定三方程序user,需要发送请求获取微信用户信息:tokenopenid

2. 配置回调域名

问:当扫码成功之后要跳转到哪个页面呢?
即使你在当前项目中定义一个页面,外网微信开发平台无法访问本地应用127.0.0.1

如果上线了:配置真实域名,但是测试阶段使用本地域名

3. 配置本地域名(注:域名换成自己购买的域名)

文件位置:C:\Windows\System32\drivers\etc\hosts
Host文件配置:127.0.0.1 bugtracker.itsource.cn
注意:bugtracker.itsource.cn是真实有效的

六. 微信授权流程

1.用户点击微信登录,发送第一个请求,弹出二维码,请求地址:

https://open.weixin.qq.com/connect/qrconnect?appid=wxd853562a0548a7d0&redirect_uri=http://bugtracker.itsource.cn/callback.html&response_type=code&scope=snsapi_login&state=1#wechat_redirect 

​ 2.用户使用手机扫码之后,点击同意授权,返回回调地址和code
​ 回调地址:上一步redirect_uri设置的地址,该地址必须是一个可以访问的域名地址,localhost不行。
​ 可以使用bugtracker.itsource.cn做测试
code:授权码
​ 3.配置回调域名:hosts文件
​ 准备callback.html回调页面,一个空页面,仅仅用来处理数据,并发送微信登录请求
​ 注意:前端拦截器已经拦截了callback.html,而且bugtracker.itsource.cn域名要访问后端服务器要配置跨域

callback.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>回调</title>

    <!--引入vue + axios-->
    <script src="js/plugins/vue/dist/vue.js"></script>
    <script src="js/plugins/axios/dist/axios.js"></script>
    <!--全局使用axios-->
    <script src="js/common.js"></script>
</head>
<body>
<div id="myDiv">

</div>
<script type="text/javascript">
    new Vue({
        el: "#myDiv",
        mounted() {
            //解析参数对象
            //http://bugtracker.itsource.cn/callback.html?code=031QtAll2kBeA64RzJol2gpcaW3QtAlk&state=1
            let url = location.href;
            // alert(url)
            let paramObj = parseUrlParams2Obj(url);

            //获取发送请求参数
            let params = {"code": paramObj.code};
            let code = paramObj.code
            //发起微信登录请求  调用微信登录接口
            this.$http.get("/login/wechat/" + code)
                .then(result => {
                    result = result.data;
                    console.log(result);
                    if (result.success) { //已经关联了 免密登录之后,需要调到主页
                        //做登录
                        //提示
                        alert("登录成功!")
                        //1.保存返回的token,logininfo到localStorage
                        let {token, loginInfo} = result.data;
                        localStorage.setItem("token", token);
                        localStorage.setItem("loginInfo", JSON.stringify(loginInfo));
                        //2.跳转到首页,显示当前登录人
                        location.href = "index.html";
                    } else { //没有关联跳转绑定页面   "?accessToken="+accessToken+"&openId="+openId;
                        let binderUrl = "http://bugtracker.itsource.cn/binder.html" + "?accessToken=" + result.data.accessToken + "&openId=" + result.data.openId;
                        location.href = binderUrl;
                    }
                })
                .catch(result => {
                    alert("系统错误");
                    console.log(result);
                })
        }
    });
</script>
</body>
</html>

common.js的全局配置文件

// axios基础路径
axios.defaults.baseURL = 'http://localhost:8080';
// axios的全局属性
Vue.prototype.$http = axios

//======================axios的前置拦截器【拦截调用后端的请求====================//
axios.interceptors.request.use(res => {
    let token = localStorage.getItem("token");
    if (token) {
        res.headers["token"] = token;
    }
    return res;
}, error => {
    Promise.reject(error)
})
//======================axios的前置拦截器【拦截调用后端的请求】====================//


//======================axios的后置拦截器【处理后台登录拦截的结果】====================//
axios.interceptors.response.use(res => {
    //后端响应的是没有登录的信息
    if (false === res.data.success && "noLogin" === res.data.message) {
        localStorage.removeItem("token");
        localStorage.removeItem("loginInfo");
        location.href = 'login.html'
    }
    return res;
}, error => {
    Promise.reject(error)
})
//======================axios的后置拦截器【处理后台登录拦截的结果】====================//


//======================路由的前端拦截器【拦截不到后端的请求】====================//
let url = location.href;//获取地址栏请求地址
// alert(url)
// 访问的不是login.html和register.html
if (url.indexOf('login.html') == -1 && url.indexOf('register.html') == -1
    && url.indexOf('binder.html') == -1 && url.indexOf('callback.html') == -1) {
    let logininfo = localStorage.getItem("loginInfo")
    if (!logininfo) {//没有登录
        location.href = 'login.html'
    }
}

//封装公用方法 - 将字符串的参数解析为json对象
function parseUrlParams2Obj(url) {//xxx?code=xxx&state=1
    let paramStr = url.substring(url.indexOf("?") + 1);//code=xxx&state=1
    let paramArr = paramStr.split("&");//[code=xxx,state=1]
    let paramObj = {};
    for (let i = 0; i < paramArr.length; i++) {
        let paramTemp = paramArr[i];//code=xxx
        let paramName = paramTemp.split("=")[0];//code
        let paramValue = paramTemp.split("=")[1];//xxx
        paramObj[paramName] = paramValue;//{code:xxx,state:1}
    }
    return paramObj;
}

七. 微信登录流程

1.在callback.html页面中解析地址栏中的code,并发送微信异步登录请求,传递code
2.后端处理微信登录请求,service业务中
  2.1.获得授权码code,和appid,SECRET一起发送获取access_token的请求
请求地址2:https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
  2.2:建议配置常量比较方便些,也比较好维护
  2.3:返回值是一个json字符串【参考官网】,想办法将其转成json对象,才能获取里面的数据【fastJsoon】
                { 
                    "access_token":"ACCESS_TOKEN", 
                    "expires_in":7200, 
                    "refresh_token":"REFRESH_TOKEN",
                    "openid":"OPENID", 
                    "scope":"SCOPE",
                    "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
                }
3.根据openid去查询微信用户信息
    a.如果有并且和user绑定了【有user_id】,说明绑定过,直接获取Logininfo对象实现免密登录
        解释1:如果没有wxuser,说明第一次登录
        解释2:如果用户以前登录过,后面注销了user信息,wxuser就关联不上了,获取级联清空了wxuser中的user_id
        疑问:为啥要将wxuser与user绑定:以后不管是微信登录还是账号登录都是同一个账户,都是自己的信息
            return true;//登录成功
    b.如果没有wxuser信息并且也没有和user_id绑定
                就通过Result将access_token和openid响应给前端,发送微信用户绑定请求
                return false;//登录失败,第一次登录需要手机验证码
    请求地址3:https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
    测试:注意,微信只能扫一次,第二次扫的时候accessToken为null

7.1 微信登录常量

//微信登录相关常量
public interface WxConstants {
    String APPID = "wxd853562a0548a7d0";
    String GET_ACK_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
    String SECRET = "4a5d5615f93f24bdba2ba8534642dbb6";
    String GET_USER_URL = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
}

7.2 微信登录业务代码

    @Override
    public Result wechatLogin(String code) {
        /*
        http请求方式: GET
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
         */
        //发送第二次请求 准备参数
        final String url = WxConstants.GET_ACK_URL.replace("APPID", WxConstants.APPID)
                .replace("SECRET", WxConstants.SECRET).replace("CODE", code);
        //发送get请求返回json字符串 返回的结果如下
        /*{
        "access_token":"ACCESS_TOKEN",
        "expires_in":7200,
        "refresh_token":"REFRESH_TOKEN",
        "openid":"OPENID",
        "scope":"SCOPE"
        }*/
        final String jsonStr = HttpUtil.httpGet(url);
        //转换json对象
        final JSONObject jsonObject = JSONObject.parseObject(jsonStr);
        final String access_token = jsonObject.getString("access_token");
        final String openid = jsonObject.getString("openid");
        //通过openid去t_wxuser中查询
        final WxUser wxUser = wxUserMapper.selectOne(new LambdaQueryWrapper<WxUser>().eq(WxUser::getOpenid, openid));
        if (wxUser != null) {//微信已经与账号关联 直接跳转不需要密码登录
            //查找user表的关联信息
            final User user = userMapper.selectById(wxUser.getUserId());
            if (user != null) {
                //查找登录信息
                final LoginInfo loginInfo = loginInfoMapper.selectById(user.getLogininfoId());
                //生成token
                final String token = UUID.randomUUID().toString();
                // 保存信息进入redis
                stringRedisTemplate.opsForValue().set(Constants.LOGIN_TOKEN + token, JSON.toJSONString(loginInfo), 30, TimeUnit.MINUTES);
                //封装返回登录的信息
                Map<String, Object> map = new HashMap<>();
                map.put("token", token);
                map.put("loginInfo", loginInfo);
                return Result.success(map);
            } else {
                return Result.fail("用户未注册");
            }
        } else {
            // 跳转微信绑定界面 "?accessToken="+accessToken+"&openId="+openId
            //5.没有 - 需要跳转页面绑定 - 响应给前端进行跳转
            Map<String, Object> map = new HashMap<>();
            map.put("accessToken", access_token);
            map.put("openId", openid);
            return Result.fail(map);
        }
    }

八. 微信绑定流程

1.callback.html发送异步请求的else中获取后端响应的access_token和openid
2.将其拼接到binder.html后跳转到binder.html页面
binder.html?accessToken=access_token&openId=openid
3.binder.html页面,输入手机号码,获取验证码
4.后端处理获取验证码请求    
5.前端binder.html页面收到验证码之后,填写验证码
  5.1.页面一加载要解析url获取access_token和openid,复制给模型数据
            phoneUserForm:{
                phone:"13330964748",
                verifyCode:null,
                accessToken:null,
                openId:null
            }
6.发送绑定微信用户请求
7.后端处理微信用户绑定请求
8.后端处理微信用户绑定请求
  8.1.校验验证码和验证码过期时间
  8.2.发送第三个请求获取wxuser信息
  8.3.将wxuser信息转成WxUser对象:WxUser wxUser = wxUserStr2WxUser(wxUserStr);
  8.4.根据电话从头t_user中获取用户信息,进行判断
  8.5.如过user==null,通过手机号构建一个User对象,密码随机的6位,并同步Logininfo信息,保存到数据库
  8.6.如果user!=null,直接就用这个user对象
  8.7.将wxUser与User绑定 = wxUser的user_id关联起来
  8.8.添加用户到t_wxUser
  8.9.免密登录

8.1 发送微信绑定请求

binder() {
    this.$http.post("/login/wechat/binder", this.phoneUserForm).then(result => {
        console.log(this.phoneUserForm)
        result = result.data;
        if (result.success) {
            alert("绑定成功!")
            //1.保存返回的token,logininfo到localStorage
            let {token, loginInfo} = result.data;
            localStorage.setItem("token", token);
            localStorage.setItem("loginInfo", JSON.stringify(loginInfo));
            location.href = "/index.html"; //注册成功后跳转登录页面
        } else {
            alert(result.msg)
        }
    }).catch(result => {
        alert("系统错误!");
    })
},

8.2 binder.html页面初始化数据

mounted() {
    let paramObj = parseUrlParams2Obj(location.href);
    if (paramObj) {
        this.phoneUserForm.accessToken = paramObj.accessToken;
        this.phoneUserForm.openId = paramObj.openId;
    }
}

8.3 绑定时获取验证码

@Override
public void binderSmsCode(PhoneCodeDTO codeDTO) {
    final String phone = codeDTO.getPhone();
    if (StrUtil.isBlank(phone)) {
        throw new BusinessException("手机号码不能为空");
    }
    // 因为微信扫码登录需要关联手机号码 判断手机号是否已经绑定微信号
    final User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getPhone, phone));
    // 用户存在
    if (user != null) {
        final WxUser wxUser = wxUserMapper.selectOne(new LambdaQueryWrapper<WxUser>().eq(WxUser::getUserId, user.getId()));
        if (wxUser != null) {
            throw new BusinessException("手机号已经绑定其它微信账号,请直接登录...");
        }
    }
    final String value = stringRedisTemplate.opsForValue().get(VerifyCodeConstants.PHONE_CODE + phone);
    String code = null;
    if (value != null) {// 验证码还未过期
        //判断是否过了重发时间
        final long oldTime = Long.parseLong((value.split(":")[1]));
        if ((System.currentTimeMillis() - oldTime) <= 60) {//间隔时间未超过一分钟
            throw new BusinessException("操作频繁,请稍后再试!");
        } else {
            code = value.split(":")[0];
        }
    } else {
        // 生成验证码
        code = RandomUtil.randomNumbers(6);
    }
    stringRedisTemplate.opsForValue().set(VerifyCodeConstants.PHONE_CODE + phone, code, 3L, TimeUnit.MINUTES);
    log.info("授权短信验证码:{}", code);
}

8.4 微信绑定业务代码

 @Override
    public Result wechatBinder(BinderDTO binderDTO) {
        final String phone = binderDTO.getPhone();
        final String verifyCode = binderDTO.getVerifyCode();
        if (StrUtil.isBlank(phone) || StrUtil.isBlank(verifyCode)) {
            throw new BusinessException("数据不能为空");
        }
        final String value = stringRedisTemplate.opsForValue().get(VerifyCodeConstants.PHONE_CODE + phone);
        if (value == null) {
            throw new BusinessException("验证码已经过期!!!");
        }
        //判断验证码输入是否正确
        if (!verifyCode.equals(value.split(":")[0])) {
            throw new BusinessException("验证码错误!!!");
        }

        String url = WxConstants.GET_USER_URL.replace("ACCESS_TOKEN", binderDTO.getAccessToken())
                .replace("OPENID", binderDTO.getOpenId());
        // 发送获取微信用户信息请求
        final String jsonStr = HttpUtil.httpGet(url);
        WxUser wxUser = jsonStr2WxUser(jsonStr);
        //查询user是否存在
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getPhone, phone));
        if (user == null) {
            //用户不存在就注册
            user = phone2User(phone);
            // 新增登录对象
            LoginInfo loginInfo = user2LoginInfo(user);
            loginInfoMapper.insert(loginInfo);
            user.setLogininfoId(loginInfo.getId());
            userMapper.insert(user);
        }
        wxUser.setUserId(user.getId());
        wxUserMapper.insert(wxUser);
        // 免密登录
        final LoginInfo loginInfo = loginInfoMapper.selectById(user.getLogininfoId());
        loginInfo.setPassword(null);
        loginInfo.setSalt(null);
        final String token = UUID.randomUUID().toString();
        // 存入redis
        stringRedisTemplate.opsForValue().set(Constants.LOGIN_TOKEN + token, JSON.toJSONString(loginInfo), 30, TimeUnit.MINUTES);
        final HashMap<String, Object> map = new HashMap<>();
        map.put("token", token);
        map.put("loginInfo", loginInfo);
        return Result.success(map);
    }

    private LoginInfo user2LoginInfo(User user) {
        final LoginInfo loginInfo = BeanUtil.copyProperties(user, LoginInfo.class);
        loginInfo.setDisable(true);
        return loginInfo;
    }

    private User phone2User(String phone) {
        final User user = new User();
        user.setPhone(phone);
        user.setUsername(phone);
        user.setState(1);
        final String salt = RandomUtil.randomString(32);//盐值
        final String pwd = RandomUtil.randomNumbers(6);//随机密码
        user.setSalt(salt);
        user.setPassword(DigestUtil.md5Hex(salt + pwd));//密码
        return user;
    }

    private WxUser jsonStr2WxUser(String jsonStr) {
        final JSONObject res = JSON.parseObject(jsonStr);
        final WxUser wxUser = new WxUser();
        wxUser.setNickname(res.getString("nickname"));
        wxUser.setSex(res.getInteger("sex"));
        wxUser.setOpenid(res.getString("openid"));
        wxUser.setHeadimgurl(res.getString("headimgurl"));
        wxUser.setUnionid(res.getString("unionid"));
        wxUser.setAddress(res.getString("country") + res.getString("province") + res.getString("city"));
        log.info("nickname:{}", res.getString("nickname"));
        log.info("city:{}", res.getString("city"));
        log.info("province:{}", res.getString("province"));
        log.info("headimgurl:{}", res.getString("headimgurl"));
        return wxUser;
    }

九. 后端发送Http请求工具类

package io.coderyeah.basic.util;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;

/**
 * http 工具类
 */
public class HttpUtil {

    public static String post(String requestUrl, String accessToken, String params)
            throws Exception {
        String contentType = "application/x-www-form-urlencoded";
        return HttpUtil.post(requestUrl, accessToken, contentType, params);
    }

    public static String post(String requestUrl, String accessToken, String contentType, String params)
            throws Exception {
        String encoding = "UTF-8";
        if (requestUrl.contains("nlp")) {
            encoding = "GBK";
        }
        return HttpUtil.post(requestUrl, accessToken, contentType, params, encoding);
    }

    public static String post(String requestUrl, String accessToken, String contentType, String params, String encoding)
            throws Exception {
        String url = requestUrl + "?access_token=" + accessToken;
        return HttpUtil.postGeneralUrl(url, contentType, params, encoding);
    }

    public static String postGeneralUrl(String generalUrl, String contentType, String params, String encoding)
            throws Exception {
        URL url = new URL(generalUrl);
        // 打开和URL之间的连接
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("POST");
        // 设置通用的请求属性
        connection.setRequestProperty("Content-Type", contentType);
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setUseCaches(false);
        connection.setDoOutput(true);
        connection.setDoInput(true);

        // 得到请求的输出流对象
        DataOutputStream out = new DataOutputStream(connection.getOutputStream());
        out.write(params.getBytes(encoding));
        out.flush();
        out.close();

        // 建立实际的连接
        connection.connect();
        // 获取所有响应头字段
        Map<String, List<String>> headers = connection.getHeaderFields();
        // 遍历所有的响应头字段
        for (String key : headers.keySet()) {
            System.err.println(key + "--->" + headers.get(key));
        }
        // 定义 BufferedReader输入流来读取URL的响应
        BufferedReader in = null;
        in = new BufferedReader(
                new InputStreamReader(connection.getInputStream(), encoding));
        String result = "";
        String getLine;
        while ((getLine = in.readLine()) != null) {
            result += getLine;
        }
        in.close();
        System.err.println("result:" + result);
        return result;
    }

    public static String httpGet(String url) {
        // 1 创建发起请求客户端
        try {
            HttpClient client = new HttpClient();
            // 2 创建要发起请求-tet
            GetMethod getMethod = new GetMethod(url);
            //            getMethod.addRequestHeader("Content-Type",
            //                    "application/x-www-form-urlencoded;charset=UTF-8");
            getMethod.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "utf8");
            // 3 通过客户端传入请求就可以发起请求,获取响应对象
            client.executeMethod(getMethod);
            // 4 提取响应json字符串返回
            String result = new String(getMethod.getResponseBodyAsString().getBytes("utf8"));
            return result;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
-------------本文结束感谢您的阅读-------------
you can reward me here. Thank you!

欢迎关注我的其它发布渠道