码迷,mamicode.com
首页 > 微信 > 详细

OAuth2实现微信登录

时间:2020-07-16 21:38:09      阅读:101      评论:0      收藏:0      [点我收藏+]

标签:instance   ota   llb   cse   manage   字符   ide   登录失败   图片   

一添加配置

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         }

 

OAuth2实现微信登录

标签:instance   ota   llb   cse   manage   字符   ide   登录失败   图片   

原文地址:https://www.cnblogs.com/lzq210288246/p/13324554.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!