微信授权

1、配置微信公众平台服务器配置

微信授权_第1张图片
微信公众平台_ 1.png

微信授权_第2张图片
微信公众平台_ 2.png

校验模块代码:

  • SignUtil (校验帮助类)
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
/**
*类名: SignUtil 
*描述: 检验signature 工具类
*开发人员: souvc
*创建时间: 2015-9-29
*发布版本:V1.0
*/ public class SignUtil { // 与接口配置信息中的Token要一致 private static String token = "souvcweixin"; /** * 方法名:checkSignature
* 详述:验证签名
* 开发人员:souvc
* 创建时间:2015-9-29
* @param signature * @param timestamp * @param nonce * @return * @throws */ public static boolean checkSignature(String signature, String timestamp,String nonce) { // 1.将token、timestamp、nonce三个参数进行字典序排序 String[] arr = new String[] { ConfigUtil.getParameter("wx_token"), timestamp, nonce }; Arrays.sort(arr); // 2. 将三个参数字符串拼接成一个字符串进行sha1加密 StringBuilder content = new StringBuilder(); for (int i = 0; i < arr.length; i++) { content.append(arr[i]); } MessageDigest md = null; String tmpStr = null; try { md = MessageDigest.getInstance("SHA-1"); // 将三个参数字符串拼接成一个字符串进行sha1加密 byte[] digest = md.digest(content.toString().getBytes()); tmpStr = byteToStr(digest); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } content = null; // 3.将sha1加密后的字符串可与signature对比,标识该请求来源于微信 return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false; } /** * 方法名:byteToStr
* 详述:将字节数组转换为十六进制字符串
* 开发人员:souvc
* 创建时间:2015-9-29
* @param byteArray * @return * @throws */ private static String byteToStr(byte[] byteArray) { String strDigest = ""; for (int i = 0; i < byteArray.length; i++) { strDigest += byteToHexStr(byteArray[i]); } return strDigest; } /** * 方法名:byteToHexStr
* 详述:将字节转换为十六进制字符串
* 开发人员:souvc
* 创建时间:2015-9-29
* @param mByte * @return * @throws */ private static String byteToHexStr(byte mByte) { char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A','B', 'C', 'D', 'E', 'F' }; char[] tempArr = new char[2]; tempArr[0] = Digit[(mByte >>> 4) & 0X0F]; tempArr[1] = Digit[mByte & 0X0F]; String s = new String(tempArr); return s; } }
  • WeiXinConteroller (接收来自微信服务的请求)
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import com.sinsinet.module.Config;
import com.sinsinet.module.SNSUserInfo;
import com.sinsinet.module.WeixinOauth2Token;
import com.sinsinet.util.ConfigUtil;
import com.sinsinet.util.SignUtil;
import com.sinsinet.util.WeixinUtil;

@Controller
@RequestMapping("/weixin")
public class WeiXinConteroller {
    
    /**
     * 接收来自微信服务的请求
     */
    @RequestMapping(method = RequestMethod.GET)
    @ResponseBody
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        // 微信加密签名
        String signature = request.getParameter("signature");
        // 时间戳
        String timestamp = request.getParameter("timestamp");
        // 随机数
        String nonce = request.getParameter("nonce");
        // 随机字符串
        String echostr = request.getParameter("echostr");

        PrintWriter out = response.getWriter();
        
        // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
        if (SignUtil.checkSignature(signature, timestamp, nonce)) {
            out.print(echostr);
        }       
        out.close();
        out = null;
    }   
}

2、网页授权获取用户基本信息

微信授权_第3张图片
微信公众平台_ - 3.png
  • 点击修改进入功能设置
微信授权_第4张图片
QQ截图20170807104329.png
  • 点击设置 设置授权回调页面域名


    微信授权_第5张图片
    QQ截图20170807105236.png

微信网页授权的详细代码

  • web.xml 配置
    
    
        oauthServlet
        com.sinsinet.service.OAuthServlet
    
    
        oauthServlet
        *.jsp
    

    
        index.jsp
    
    
  • OAuthServlet
import java.io.IOException;
import java.util.Date;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.sinsinet.mapper.UserMapper;
import com.sinsinet.module.SNSUserInfo;
import com.sinsinet.module.User;
import com.sinsinet.module.WeixinOauth2Token;
import com.sinsinet.util.CommonUtil;
import com.sinsinet.util.ConfigUtil;
import com.sinsinet.util.TokenUtil;
import com.sinsinet.util.WeixinUtil;


/**
* 类名: OAuthServlet 
* 描述: 授权后的回调请求处理
* 开发人员: souvc
* 创建时间: 2015-11-27
* 发布版本:V1.0
*/ public class OAuthServlet extends HttpServlet { @Resource UserMapper mUserMapper; private static final long serialVersionUID = -1847238807216447030L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); // 用户同意授权后,能获取到code String code = request.getParameter("code"); String state = request.getParameter("state"); // 用户同意授权 if (!"authdeny".equals(code)) { // 获取网页授权access_token WeixinOauth2Token weixinOauth2Token = WeixinUtil.getOauth2AccessToken(ConfigUtil.getParameter("wx_AppId"),ConfigUtil.getParameter("wx_AppSecret"),code); // 网页授权接口访问凭证 String accessToken = weixinOauth2Token.getAccessToken(); // 用户标识 String openId = weixinOauth2Token.getOpenId(); // 获取用户信息 SNSUserInfo snsUserInfo = WeixinUtil.getSNSUserInfo(accessToken, openId); User user = mUserMapper.findByOpenid(openId); if (user == null) { user.setOpenid(snsUserInfo.getOpenId()); user.setWxName(snsUserInfo.getNickname()); user.setSex(snsUserInfo.getSex()); user.setRole(3); user.setCreateTime(new Date()); mUserMapper.insert(user); user = mUserMapper.findByOpenid(openId); } // 设置要传递的参数 request.setAttribute("user", user); request.setAttribute("state", state); } // 跳转到index.jsp request.getRequestDispatcher("index.jsp").forward(request, response); } }
  • WeixinOauth2Token
public class WeixinOauth2Token {
    
    // 网页授权接口调用凭证
    private String accessToken;
    // 凭证有效时长
    private int expiresIn;
    // 用于刷新凭证
    private String refreshToken;
    // 用户标识
    private String openId;
    // 用户授权作用域
    private String scope;

    public String getAccessToken() {
        return accessToken;
    }

    public void setAccessToken(String accessToken) {
        this.accessToken = accessToken;
    }

    public int getExpiresIn() {
        return expiresIn;
    }

    public void setExpiresIn(int expiresIn) {
        this.expiresIn = expiresIn;
    }

    public String getRefreshToken() {
        return refreshToken;
    }

    public void setRefreshToken(String refreshToken) {
        this.refreshToken = refreshToken;
    }

    public String getOpenId() {
        return openId;
    }

    public void setOpenId(String openId) {
        this.openId = openId;
    }

    public String getScope() {
        return scope;
    }

    public void setScope(String scope) {
        this.scope = scope;
    }

}
  • SNSUserInfo
import java.util.List;

/**
* 类名: SNSUserInfo 
* 描述: 通过网页授权获取的用户信息
* 开发人员: souvc
* 创建时间: 2015-11-27
* 发布版本:V1.0
*/ public class SNSUserInfo { // 用户标识 private String openId; // 用户昵称 private String nickname; // 性别(1是男性,2是女性,0是未知) private int sex; // 国家 private String country; // 省份 private String province; // 城市 private String city; // 用户头像链接 private String headImgUrl; // 用户特权信息 private List privilegeList; public String getOpenId() { return openId; } public void setOpenId(String openId) { this.openId = openId; } public String getNickname() { return nickname; } public void setNickname(String nickname) { this.nickname = nickname; } public int getSex() { return sex; } public void setSex(int sex) { this.sex = sex; } public String getCountry() { return country; } public void setCountry(String country) { this.country = country; } public String getProvince() { return province; } public void setProvince(String province) { this.province = province; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getHeadImgUrl() { return headImgUrl; } public void setHeadImgUrl(String headImgUrl) { this.headImgUrl = headImgUrl; } public List getPrivilegeList() { return privilegeList; } public void setPrivilegeList(List privilegeList) { this.privilegeList = privilegeList; } }
  • WeixinUtil
import java.awt.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sinsinet.module.SNSUserInfo;
import com.sinsinet.module.WeixinOauth2Token;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;



public class WeixinUtil {
    
    static Logger log = LoggerFactory.getLogger(WeixinUtil.class);
    
    
    
    /**
     * 获取网页授权凭证
     * 
     * @param appId 公众账号的唯一标识
     * @param appSecret 公众账号的密钥
     * @param code
     * @return WeixinAouth2Token
     */
    public static WeixinOauth2Token getOauth2AccessToken(String appId, String appSecret, String code) {
        WeixinOauth2Token wat = null;
        // 拼接请求地址
        String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
        requestUrl = requestUrl.replace("APPID", appId);
        requestUrl = requestUrl.replace("SECRET", appSecret);
        requestUrl = requestUrl.replace("CODE", code);
        // 获取网页授权凭证
        JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);
        if (null != jsonObject) {
            try {
                wat = new WeixinOauth2Token();
                wat.setAccessToken(jsonObject.getString("access_token"));
                wat.setExpiresIn(jsonObject.getInt("expires_in"));
                wat.setRefreshToken(jsonObject.getString("refresh_token"));
                wat.setOpenId(jsonObject.getString("openid"));
                wat.setScope(jsonObject.getString("scope"));
            } catch (Exception e) {
                wat = null;
                int errorCode = jsonObject.getInt("errcode");
                String errorMsg = jsonObject.getString("errmsg");
                log.error("获取网页授权凭证失败 errcode:{} errmsg:{}", errorCode, errorMsg);
            }
        }
        return wat;
    }
    
    /**
     * 通过网页授权获取用户信息
     * 
     * @param accessToken 网页授权接口调用凭证
     * @param openId 用户标识
     * @return SNSUserInfo
     */
    @SuppressWarnings( { "deprecation", "unchecked" })
    public static SNSUserInfo getSNSUserInfo(String accessToken, String openId) {
        SNSUserInfo snsUserInfo = null;
        // 拼接请求地址
        String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID";
        requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);
        // 通过网页授权获取用户信息
        JSONObject jsonObject = CommonUtil.httpsRequest(requestUrl, "GET", null);

        if (null != jsonObject) {
            try {
                snsUserInfo = new SNSUserInfo();
                // 用户的标识
                snsUserInfo.setOpenId(jsonObject.getString("openid"));
                // 昵称
                snsUserInfo.setNickname(jsonObject.getString("nickname"));
                // 性别(1是男性,2是女性,0是未知)
                snsUserInfo.setSex(jsonObject.getInt("sex"));
                // 用户所在国家
                snsUserInfo.setCountry(jsonObject.getString("country"));
                // 用户所在省份
                snsUserInfo.setProvince(jsonObject.getString("province"));
                // 用户所在城市
                snsUserInfo.setCity(jsonObject.getString("city"));
                // 用户头像
                snsUserInfo.setHeadImgUrl(jsonObject.getString("headimgurl"));
                // 用户特权信息
                snsUserInfo.setPrivilegeList(JSONArray.toList(jsonObject.getJSONArray("privilege"), List.class));
            } catch (Exception e) {
                snsUserInfo = null;
                int errorCode = jsonObject.getInt("errcode");
                String errorMsg = jsonObject.getString("errmsg");
                log.error("获取用户信息失败 errcode:{} errmsg:{}", errorCode, errorMsg);
            }
        }
        return snsUserInfo;
    }
}
  • 发送https请求方法(我的放在l了CommonUtil里)
     * 发送https请求
     * 
     * @param requestUrl 请求地址
     * @param requestMethod 请求方式(GET、POST)
     * @param outputStr 提交的数据
     * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
     */
    public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
        JSONObject jsonObject = null;
        try {
            // 创建SSLContext对象,并使用我们指定的信任管理器初始化
            TrustManager[] tm = { new MyX509TrustManager() };
            SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
            sslContext.init(null, tm, new java.security.SecureRandom());
            // 从上述SSLContext对象中得到SSLSocketFactory对象
            SSLSocketFactory ssf = sslContext.getSocketFactory();

            URL url = new URL(requestUrl);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(ssf);
            
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            // 设置请求方式(GET/POST)
            conn.setRequestMethod(requestMethod);

            // 当outputStr不为null时向输出流写数据
            if (null != outputStr) {
                OutputStream outputStream = conn.getOutputStream();
                // 注意编码格式
                outputStream.write(outputStr.getBytes("UTF-8"));
                outputStream.close();
            }

            // 从输入流读取返回内容
            InputStream inputStream = conn.getInputStream();
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String str = null;
            StringBuffer buffer = new StringBuffer();
            while ((str = bufferedReader.readLine()) != null) {
                buffer.append(str);
            }

            // 释放资源
            bufferedReader.close();
            inputStreamReader.close();
            inputStream.close();
            inputStream = null;
            conn.disconnect();
            jsonObject = JSONObject.fromObject(buffer.toString());
        } catch (ConnectException ce) {
            log.error("连接超时:{}", ce);
        } catch (Exception e) {
            log.error("https请求异常:{}", e);
        }
        return jsonObject;
    }
  • MyX509TrustManager (信任管理器 )
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;

/**
* 类名: MyX509TrustManager 
* 描述:信任管理器
* 开发人员: souvc
* 创建时间: 2015-11-27
* 发布版本:V1.0
*/ public class MyX509TrustManager implements X509TrustManager { // 检查客户端证书 public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } // 检查服务器端证书 public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } // 返回受信任的X509证书数组 public X509Certificate[] getAcceptedIssuers() { return null; } }

3、测试

  • 在微信客户端中打开此链接

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
需要修改的地方:

(1)替换自己的AppID
(2)将redirect_url换成自己的授权请求链接URL。注意这个连接需要经过UTF-8编码。
(3)需要修改scope。需要弹出页面则要修改为snsapi_userinfo 。

参考文档

http://www.cnblogs.com/liuhongfeng/p/5099149.html

你可能感兴趣的:(微信授权)