zoukankan      html  css  js  c++  java
  • OAuth2实现微信登录

    一添加配置

    1 # 微信开放平台 appid
    2 wx.open.app_id=wxed9954c01bb89b47
    3 # 微信开放平台 appsecret
    4 wx.open.app_secret=a7482517235173ddb4083788de60b90e
    5 # 微信开放平台 重定向url
    6 wx.open.redirect_url=http://guli.shop/api/ucenter/wx/callback

    二创建util包,创建ConstantPropertiesUtil.java常量类,读取配置信息

     1 package com.atguigu.eduservice.uitls;
     2 
     3 import org.springframework.beans.factory.InitializingBean;
     4 import org.springframework.beans.factory.annotation.Value;
     5 import org.springframework.stereotype.Component;
     6 
     7 /**
     8  * Author: noob
     9  * DATE: 2020/7/16 0016
    10  * PROJECT: guli_parent
    11  * DESCRIPTION: 读取配置文件的值
    12  **/
    13 @Component
    14 public class ConstanWxUtils  implements InitializingBean{
    15     @Value("${wx.open.app_id}")
    16     private String appId;
    17     @Value("${wx.open.app_secret}")
    18     private String appSecret;
    19     @Value("${wx.open.redirect_url}")
    20 
    21 
    22     private String redirectUrl;
    23     public static String WX_OPEN_APP_ID;
    24     public static String WX_OPEN_APP_SECRET;
    25     public static String WX_OPEN_REDIRECT_URL;
    26     @Override
    27     public void afterPropertiesSet() throws Exception {
    28         WX_OPEN_APP_ID = appId;
    29         WX_OPEN_APP_SECRET = appSecret;
    30         WX_OPEN_REDIRECT_URL = redirectUrl;
    31 
    32     }
    33 }

    三生成二维码图片,当我们扫描后会获得一个code

     1 @GetMapping("login")
     2     public String getWxCode() {
     3         //固定地址,后面拼接参数
     4 //        String url = "https://open.weixin.qq.com/" +
     5 //                "connect/qrconnect?appid="+ ConstantWxUtils.WX_OPEN_APP_ID+"&response_type=code";
     6 
     7         // 微信开放平台授权baseUrl  %s相当于?代表占位符
     8         String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
     9                 "?appid=%s" +
    10                 "&redirect_uri=%s" +
    11                 "&response_type=code" +
    12                 "&scope=snsapi_login" +
    13                 "&state=%s" +
    14                 "#wechat_redirect";
    15 
    16         //对redirect_url进行URLEncoder编码
    17         String redirectUrl = ConstanWxUtils.WX_OPEN_REDIRECT_URL;
    18         try {
    19             redirectUrl = URLEncoder.encode(redirectUrl, "utf-8");
    20         }catch(Exception e) {
    21         }
    22 
    23         //设置%s里面值
    24         String url = String.format(
    25                     baseUrl,
    26                      ConstanWxUtils.WX_OPEN_APP_ID,
    27                     redirectUrl,
    28                     "atguigu"
    29                  );
    30 
    31         //重定向到请求微信地址里面
    32         return "redirect:"+url;
    33     }

    四当登录成功,会获得code和state,回调到http://8150/api/ucenter/wx/callback?code=xx&state=xx

    五导入HttpClientUtils这个工具类

      1 package com.atguigu.eduservice.uitls;
      2 
      3 import org.apache.commons.io.IOUtils;
      4 import org.apache.commons.lang.StringUtils;
      5 import org.apache.http.Consts;
      6 import org.apache.http.HttpEntity;
      7 import org.apache.http.HttpResponse;
      8 import org.apache.http.NameValuePair;
      9 import org.apache.http.client.HttpClient;
     10 import org.apache.http.client.config.RequestConfig;
     11 import org.apache.http.client.config.RequestConfig.Builder;
     12 import org.apache.http.client.entity.UrlEncodedFormEntity;
     13 import org.apache.http.client.methods.HttpGet;
     14 import org.apache.http.client.methods.HttpPost;
     15 import org.apache.http.conn.ConnectTimeoutException;
     16 import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
     17 import org.apache.http.conn.ssl.SSLContextBuilder;
     18 import org.apache.http.conn.ssl.TrustStrategy;
     19 import org.apache.http.conn.ssl.X509HostnameVerifier;
     20 import org.apache.http.entity.ContentType;
     21 import org.apache.http.entity.StringEntity;
     22 import org.apache.http.impl.client.CloseableHttpClient;
     23 import org.apache.http.impl.client.HttpClients;
     24 import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
     25 import org.apache.http.message.BasicNameValuePair;
     26 
     27 import javax.net.ssl.SSLContext;
     28 import javax.net.ssl.SSLException;
     29 import javax.net.ssl.SSLSession;
     30 import javax.net.ssl.SSLSocket;
     31 import java.io.IOException;
     32 import java.net.SocketTimeoutException;
     33 import java.security.GeneralSecurityException;
     34 import java.security.cert.CertificateException;
     35 import java.security.cert.X509Certificate;
     36 import java.util.ArrayList;
     37 import java.util.List;
     38 import java.util.Map;
     39 import java.util.Map.Entry;
     40 import java.util.Set;
     41 
     42 /**
     43  *  依赖的jar包有:commons-lang-2.6.jar、httpclient-4.3.2.jar、httpcore-4.3.1.jar、commons-io-2.4.jar
     44  * @author zhaoyb
     45  *
     46  */
     47 public class HttpClientUtils {
     48 
     49     public static final int connTimeout=10000;
     50     public static final int readTimeout=10000;
     51     public static final String charset="UTF-8";
     52     private static HttpClient client = null;
     53 
     54     static {
     55         PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
     56         cm.setMaxTotal(128);
     57         cm.setDefaultMaxPerRoute(128);
     58         client = HttpClients.custom().setConnectionManager(cm).build();
     59     }
     60 
     61     public static String postParameters(String url, String parameterStr) throws ConnectTimeoutException, SocketTimeoutException, Exception{
     62         return post(url,parameterStr,"application/x-www-form-urlencoded",charset,connTimeout,readTimeout);
     63     }
     64 
     65     public static String postParameters(String url, String parameterStr,String charset, Integer connTimeout, Integer readTimeout) throws ConnectTimeoutException, SocketTimeoutException, Exception{
     66         return post(url,parameterStr,"application/x-www-form-urlencoded",charset,connTimeout,readTimeout);
     67     }
     68 
     69     public static String postParameters(String url, Map<String, String> params) throws ConnectTimeoutException,
     70             SocketTimeoutException, Exception {
     71         return postForm(url, params, null, connTimeout, readTimeout);
     72     }
     73 
     74     public static String postParameters(String url, Map<String, String> params, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,
     75             SocketTimeoutException, Exception {
     76         return postForm(url, params, null, connTimeout, readTimeout);
     77     }
     78 
     79     public static String get(String url) throws Exception {
     80         return get(url, charset, null, null);
     81     }
     82 
     83     public static String get(String url, String charset) throws Exception {
     84         return get(url, charset, connTimeout, readTimeout);
     85     }
     86 
     87     /**
     88      * 发送一个 Post 请求, 使用指定的字符集编码.
     89      *
     90      * @param url
     91      * @param body RequestBody
     92      * @param mimeType 例如 application/xml "application/x-www-form-urlencoded" a=1&b=2&c=3
     93      * @param charset 编码
     94      * @param connTimeout 建立链接超时时间,毫秒.
     95      * @param readTimeout 响应超时时间,毫秒.
     96      * @return ResponseBody, 使用指定的字符集编码.
     97      * @throws ConnectTimeoutException 建立链接超时异常
     98      * @throws SocketTimeoutException  响应超时
     99      * @throws Exception
    100      */
    101     public static String post(String url, String body, String mimeType,String charset, Integer connTimeout, Integer readTimeout)
    102             throws ConnectTimeoutException, SocketTimeoutException, Exception {
    103         HttpClient client = null;
    104         HttpPost post = new HttpPost(url);
    105         String result = "";
    106         try {
    107             if (StringUtils.isNotBlank(body)) {
    108                 HttpEntity entity = new StringEntity(body, ContentType.create(mimeType, charset));
    109                 post.setEntity(entity);
    110             }
    111             // 设置参数
    112             Builder customReqConf = RequestConfig.custom();
    113             if (connTimeout != null) {
    114                 customReqConf.setConnectTimeout(connTimeout);
    115             }
    116             if (readTimeout != null) {
    117                 customReqConf.setSocketTimeout(readTimeout);
    118             }
    119             post.setConfig(customReqConf.build());
    120 
    121             HttpResponse res;
    122             if (url.startsWith("https")) {
    123                 // 执行 Https 请求.
    124                 client = createSSLInsecureClient();
    125                 res = client.execute(post);
    126             } else {
    127                 // 执行 Http 请求.
    128                 client = HttpClientUtils.client;
    129                 res = client.execute(post);
    130             }
    131             result = IOUtils.toString(res.getEntity().getContent(), charset);
    132         } finally {
    133             post.releaseConnection();
    134             if (url.startsWith("https") && client != null&& client instanceof CloseableHttpClient) {
    135                 ((CloseableHttpClient) client).close();
    136             }
    137         }
    138         return result;
    139     }
    140 
    141 
    142     /**
    143      * 提交form表单
    144      *
    145      * @param url
    146      * @param params
    147      * @param connTimeout
    148      * @param readTimeout
    149      * @return
    150      * @throws ConnectTimeoutException
    151      * @throws SocketTimeoutException
    152      * @throws Exception
    153      */
    154     public static String postForm(String url, Map<String, String> params, Map<String, String> headers, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,
    155             SocketTimeoutException, Exception {
    156 
    157         HttpClient client = null;
    158         HttpPost post = new HttpPost(url);
    159         try {
    160             if (params != null && !params.isEmpty()) {
    161                 List<NameValuePair> formParams = new ArrayList<NameValuePair>();
    162                 Set<Entry<String, String>> entrySet = params.entrySet();
    163                 for (Entry<String, String> entry : entrySet) {
    164                     formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
    165                 }
    166                 UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, Consts.UTF_8);
    167                 post.setEntity(entity);
    168             }
    169 
    170             if (headers != null && !headers.isEmpty()) {
    171                 for (Entry<String, String> entry : headers.entrySet()) {
    172                     post.addHeader(entry.getKey(), entry.getValue());
    173                 }
    174             }
    175             // 设置参数
    176             Builder customReqConf = RequestConfig.custom();
    177             if (connTimeout != null) {
    178                 customReqConf.setConnectTimeout(connTimeout);
    179             }
    180             if (readTimeout != null) {
    181                 customReqConf.setSocketTimeout(readTimeout);
    182             }
    183             post.setConfig(customReqConf.build());
    184             HttpResponse res = null;
    185             if (url.startsWith("https")) {
    186                 // 执行 Https 请求.
    187                 client = createSSLInsecureClient();
    188                 res = client.execute(post);
    189             } else {
    190                 // 执行 Http 请求.
    191                 client = HttpClientUtils.client;
    192                 res = client.execute(post);
    193             }
    194             return IOUtils.toString(res.getEntity().getContent(), "UTF-8");
    195         } finally {
    196             post.releaseConnection();
    197             if (url.startsWith("https") && client != null
    198                     && client instanceof CloseableHttpClient) {
    199                 ((CloseableHttpClient) client).close();
    200             }
    201         }
    202     }
    203 
    204 
    205 
    206 
    207     /**
    208      * 发送一个 GET 请求
    209      *
    210      * @param url
    211      * @param charset
    212      * @param connTimeout  建立链接超时时间,毫秒.
    213      * @param readTimeout  响应超时时间,毫秒.
    214      * @return
    215      * @throws ConnectTimeoutException   建立链接超时
    216      * @throws SocketTimeoutException   响应超时
    217      * @throws Exception
    218      */
    219     public static String get(String url, String charset, Integer connTimeout,Integer readTimeout)
    220             throws ConnectTimeoutException,SocketTimeoutException, Exception {
    221 
    222         HttpClient client = null;
    223         HttpGet get = new HttpGet(url);
    224         String result = "";
    225         try {
    226             // 设置参数
    227             Builder customReqConf = RequestConfig.custom();
    228             if (connTimeout != null) {
    229                 customReqConf.setConnectTimeout(connTimeout);
    230             }
    231             if (readTimeout != null) {
    232                 customReqConf.setSocketTimeout(readTimeout);
    233             }
    234             get.setConfig(customReqConf.build());
    235 
    236             HttpResponse res = null;
    237 
    238             if (url.startsWith("https")) {
    239                 // 执行 Https 请求.
    240                 client = createSSLInsecureClient();
    241                 res = client.execute(get);
    242             } else {
    243                 // 执行 Http 请求.
    244                 client = HttpClientUtils.client;
    245                 res = client.execute(get);
    246             }
    247 
    248             result = IOUtils.toString(res.getEntity().getContent(), charset);
    249         } finally {
    250             get.releaseConnection();
    251             if (url.startsWith("https") && client != null && client instanceof CloseableHttpClient) {
    252                 ((CloseableHttpClient) client).close();
    253             }
    254         }
    255         return result;
    256     }
    257 
    258 
    259     /**
    260      * 从 response 里获取 charset
    261      *
    262      * @param ressponse
    263      * @return
    264      */
    265     @SuppressWarnings("unused")
    266     private static String getCharsetFromResponse(HttpResponse ressponse) {
    267         // Content-Type:text/html; charset=GBK
    268         if (ressponse.getEntity() != null  && ressponse.getEntity().getContentType() != null && ressponse.getEntity().getContentType().getValue() != null) {
    269             String contentType = ressponse.getEntity().getContentType().getValue();
    270             if (contentType.contains("charset=")) {
    271                 return contentType.substring(contentType.indexOf("charset=") + 8);
    272             }
    273         }
    274         return null;
    275     }
    276 
    277 
    278 
    279     /**
    280      * 创建 SSL连接
    281      * @return
    282      * @throws GeneralSecurityException
    283      */
    284     private static CloseableHttpClient createSSLInsecureClient() throws GeneralSecurityException {
    285         try {
    286             SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
    287                 public boolean isTrusted(X509Certificate[] chain,String authType) throws CertificateException {
    288                     return true;
    289                 }
    290             }).build();
    291 
    292             SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {
    293 
    294                 @Override
    295                 public boolean verify(String arg0, SSLSession arg1) {
    296                     return true;
    297                 }
    298 
    299                 @Override
    300                 public void verify(String host, SSLSocket ssl)
    301                         throws IOException {
    302                 }
    303 
    304                 @Override
    305                 public void verify(String host, X509Certificate cert)
    306                         throws SSLException {
    307                 }
    308 
    309                 @Override
    310                 public void verify(String host, String[] cns,
    311                                    String[] subjectAlts) throws SSLException {
    312                 }
    313 
    314             });
    315 
    316             return HttpClients.custom().setSSLSocketFactory(sslsf).build();
    317 
    318         } catch (GeneralSecurityException e) {
    319             throw e;
    320         }
    321     }
    322 
    323     public static void main(String[] args) {
    324         try {
    325             String str= post("https://localhost:443/ssl/test.shtml","name=12&page=34","application/x-www-form-urlencoded", "UTF-8", 10000, 10000);
    326             //String str= get("https://localhost:443/ssl/test.shtml?name=12&page=34","GBK");
    327             /*Map<String,String> map = new HashMap<String,String>();
    328             map.put("name", "111");
    329             map.put("page", "222");
    330             String str= postForm("https://localhost:443/ssl/test.shtml",map,null, 10000, 10000);*/
    331             System.out.println(str);
    332         } catch (ConnectTimeoutException e) {
    333             // TODO Auto-generated catch block
    334             e.printStackTrace();
    335         } catch (SocketTimeoutException e) {
    336             // TODO Auto-generated catch block
    337             e.printStackTrace();
    338         } catch (Exception e) {
    339             // TODO Auto-generated catch block
    340             e.printStackTrace();
    341         }
    342     }
    343 
    344 }

    六根据code调用微信特定方法获得access_token和openid

     1  try {
     2             //1 获取code值,临时票据,类似于验证码
     3             //2 拿着code请求 微信固定的地址,得到两个值 accsess_token 和 openid
     4             String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
     5                     "?appid=%s" +
     6                     "&secret=%s" +
     7                     "&code=%s" +
     8                     "&grant_type=authorization_code";
     9             //拼接三个参数 :id  秘钥 和 code值
    10             String accessTokenUrl = String.format(
    11                     baseAccessTokenUrl,
    12                     ConstanWxUtils.WX_OPEN_APP_ID,
    13                     ConstanWxUtils.WX_OPEN_APP_SECRET,
    14                     code
    15             );
    16             //请求这个拼接好的地址,得到返回两个值 accsess_token 和 openid
    17             //使用httpclient发送请求,得到返回结果
    18             String accessTokenInfo = HttpClientUtils.get(accessTokenUrl);
    19 
    20             //从accessTokenInfo字符串获取出来两个值 accsess_token 和 openid
    21             //把accessTokenInfo字符串转换map集合,根据map里面key获取对应值
    22             //使用json转换工具 Gson
    23             Gson gson = new Gson();
    24             HashMap mapAccessToken = gson.fromJson(accessTokenInfo, HashMap.class);
    25             String access_token = (String)mapAccessToken.get("access_token");
    26             String openid = (String)mapAccessToken.get("openid");

    七根据access_token和openid访问微信特定函数,得到用户信息

     1 /把扫描人信息添加数据库里面
     2             //判断数据表里面是否存在相同微信信息,根据openid判断
     3             UcenterMember member = memberService.getOpenIdMember(openid);
     4             if(member == null) {//memeber是空,表没有相同微信数据,进行添加
     5 
     6                 //3 拿着得到accsess_token 和 openid,再去请求微信提供固定的地址,获取到扫描人信息
     7                 //访问微信的资源服务器,获取用户信息
     8                 String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
     9                         "?access_token=%s" +
    10                         "&openid=%s";
    11                 //拼接两个参数
    12                 String userInfoUrl = String.format(
    13                         baseUserInfoUrl,
    14                         access_token,
    15                         openid
    16                 );
    17                 //发送请求
    18                 String userInfo = HttpClientUtils.get(userInfoUrl);
    19                 //获取返回userinfo字符串扫描人信息
    20                 HashMap userInfoMap = gson.fromJson(userInfo, HashMap.class);
    21                 String nickname = (String)userInfoMap.get("nickname");//昵称
    22                 String headimgurl = (String)userInfoMap.get("headimgurl");//头像
    23 
    24                 member = new UcenterMember();
    25                 member.setOpenid(openid);
    26                 member.setNickname(nickname);
    27                 member.setAvatar(headimgurl);
    28                 memberService.save(member);
    29             }
    30 
    31             //使用jwt根据member对象生成token字符串
    32             String jwtToken = JwtUtils.getJwtToken(member.getId(), member.getNickname());
    33             //最后:返回首页面,通过路径传递token字符串
    34             return "redirect:http://localhost:3000?token="+jwtToken;
    35         }catch(Exception e) {
    36             throw new GuliException(20001,"登录失败");
    37         }
  • 相关阅读:
    Atitit.ide eclipse编译速度慢的解决
    Atitit.ide eclipse编译速度慢的解决
    Atitit.可视化与报表原理与概论
    Atitit.可视化与报表原理与概论
    Atitit.数据检索与网络爬虫与数据采集的原理概论
    Atitit.数据检索与网络爬虫与数据采集的原理概论
    Atitit 游戏的原理与概论attilax总结
    Atitit 游戏的原理与概论attilax总结
    Atiti.ui原理与gui理论
    Atiti.ui原理与gui理论
  • 原文地址:https://www.cnblogs.com/lzq210288246/p/13324554.html
Copyright © 2011-2022 走看看