基于OAuth2.0协议方式

什么是OAuth

OAuth: OAuth(开放授权)是一个开放标准,允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方网站或分享他们数据的所有内容。

OAuth2.0

对于用户相关的OpenAPI(例如获取用户信息,动态同步,照片,日志,分享等),为了保护用户数据的安全和隐私,第三方网站访问用户数据前都需要显式的向用户征求授权。

QQ登录OAuth2.0采用OAuth2.0标准协议来进行用户身份验证和获取用户授权,相对于之前的OAuth1.0协议,其认证流程更简单和安全。

OAuth2.0总体处理流程

1 第一步:用户同意授权,获取code

2 第二步:通过code换取网页授权access_token

3 第三步:刷新access_token(如果需要)

4 第四步:拉取用户信息(需scope为 snsapi_userinfo)

实现微信授权获取信息

微信网页授权地址

https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842

https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

1.填写网页授权回调地址权限

2.生成网页授权地址

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx5c43fde3c9733d9e&redirect_uri=http://meitedu.s1.natapp.cc&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

3.跳转到回调地址获取授权码

http://meitedu.s1.natapp.cc/?code=061yIRgM13IOc41ZQveM1tODgM1yIRge&state=STATE

4. 通过code换取网页授权access_token

https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx5c43fde3c9733d9e&secret=b8b217126c33a5fb7074927d5e72a81a&code=061WfM4E0TABnc2Cv04E02Lb5E0WfM4b&grant_type=authorization_code

4. 拉取用户信息(需scope为 snsapi_userinfo)

https://api.weixin.qq.com/sns/userinfo?access_token=11_ZsmU50peG5LkOxn6XiFwXl9PRmlAlrFvWZ9fgxd3OM-vbiAHt_uf7gqG9iA9MnfIqf375eI8rkxf6GyqdsAkWw&openid=okYSmtzp4wWCrDCncMfGSRECVSeM&lang=zh_CN

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.learn</groupId><artifactId>oauth_web</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.0.RELEASE</version></parent><dependencies><!-- SpringBoot 对lombok 支持 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!-- SpringBoot web 核心组件 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-tomcat</artifactId></dependency><!-- SpringBoot 外部tomcat支持 --><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-jasper</artifactId></dependency><!-- springboot-log4j --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j</artifactId><version>1.3.8.RELEASE</version></dependency><!-- springboot-aop 技术 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><!-- https://mvnrepository.com/artifact/commons-lang/commons-lang --><dependency><groupId>commons-lang</groupId><artifactId>commons-lang</artifactId><version>2.6</version></dependency><!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient --><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId></dependency><!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>jstl</artifactId></dependency><dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version></dependency></dependencies>
</project>
appid=wx5c43fde3c9733d9e
secret=b8b217126c33a5fb7074927d5e72a81a
redirectUri=http://127.0.0.1:8080/callback
authorizedUrl=https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
access_token=https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
userinfo=https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
package com.learn.base;import org.springframework.stereotype.Component;import com.learn.utils.Constants;@Component
public class BaseApiService {public ResponseBase setResultError(Integer code, String msg) {return setResult(code, msg, null);}// 返回错误,可以传msgpublic ResponseBase setResultError(String msg) {return setResult(Constants.HTTP_RES_CODE_500, msg, null);}// 返回成功,可以传data值public ResponseBase setResultSuccessData(Object data) {return setResult(Constants.HTTP_RES_CODE_200, Constants.HTTP_RES_CODE_200_VALUE, data);}public ResponseBase setResultSuccessData(Integer code, Object data) {return setResult(code, Constants.HTTP_RES_CODE_200_VALUE, data);}// 返回成功,沒有data值public ResponseBase setResultSuccess() {return setResult(Constants.HTTP_RES_CODE_200, Constants.HTTP_RES_CODE_200_VALUE, null);}// 返回成功,沒有data值public ResponseBase setResultSuccess(String msg) {return setResult(Constants.HTTP_RES_CODE_200, msg, null);}// 通用封装public ResponseBase setResult(Integer code, String msg, Object data) {return new ResponseBase(code, msg, data);}}
package com.learn.base;public class ResponseBase {private Integer rtnCode;private String msg;private Object data;public ResponseBase() {}public ResponseBase(Integer rtnCode, String msg, Object data) {super();this.rtnCode = rtnCode;this.msg = msg;this.data = data;}public Integer getRtnCode() {return rtnCode;}public void setRtnCode(Integer rtnCode) {this.rtnCode = rtnCode;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}public static void main(String[] args) {ResponseBase responseBase = new ResponseBase();responseBase.setData("123456");responseBase.setMsg("success");responseBase.setRtnCode(200);System.out.println(responseBase.toString());}@Overridepublic String toString() {return "ResponseBase [rtnCode=" + rtnCode + ", msg=" + msg + ", data=" + data + "]";}}
package com.learn.entity;public class AppEntity {private long id;private String appId;private String appName;private String appSecret;private String accessToken;private String redirectUri;private int isFlag;/*** @return the id*/public long getId() {return id;}/*** @param id*            the id to set*/public void setId(long id) {this.id = id;}/*** @return the appId*/public String getAppId() {return appId;}/*** @param appId*            the appId to set*/public void setAppId(String appId) {this.appId = appId;}/*** @return the appName*/public String getAppName() {return appName;}/*** @param appName*            the appName to set*/public void setAppName(String appName) {this.appName = appName;}/*** @return the appSecret*/public String getAppSecret() {return appSecret;}/*** @param appSecret*            the appSecret to set*/public void setAppSecret(String appSecret) {this.appSecret = appSecret;}/*** @return the isFlag*/public int getIsFlag() {return isFlag;}/*** @param isFlag*            the isFlag to set*/public void setIsFlag(int isFlag) {this.isFlag = isFlag;}/*** @return the accessToken*/public String getAccessToken() {return accessToken;}/*** @param accessToken*            the accessToken to set*/public void setAccessToken(String accessToken) {this.accessToken = accessToken;}/*** @return the redirectUri*/public String getRedirectUri() {return redirectUri;}/*** @param redirectUri*            the redirectUri to set*/public void setRedirectUri(String redirectUri) {this.redirectUri = redirectUri;}}
package com.learn.entity;public class ResponseBase {private Integer rtnCode;private String msg;private Object data;public ResponseBase() {}public ResponseBase(Integer rtnCode, String msg, Object data) {super();this.rtnCode = rtnCode;this.msg = msg;this.data = data;}public Integer getRtnCode() {return rtnCode;}public void setRtnCode(Integer rtnCode) {this.rtnCode = rtnCode;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}public static void main(String[] args) {ResponseBase responseBase = new ResponseBase();responseBase.setData("123456");responseBase.setMsg("success");responseBase.setRtnCode(200);System.out.println(responseBase.toString());}@Overridepublic String toString() {return "ResponseBase [rtnCode=" + rtnCode + ", msg=" + msg + ", data=" + data + "]";}}
package com.learn.utils;public interface Constants {// 响应请求成功String HTTP_RES_CODE_200_VALUE = "success";// 系统错误String HTTP_RES_CODE_500_VALUE = "fial";// 响应请求成功codeInteger HTTP_RES_CODE_200 = 200;// 系统错误Integer HTTP_RES_CODE_500 = 500;// 未关联QQ账号Integer HTTP_RES_CODE_201 = 201;// 发送邮件String MSG_EMAIL = "email";// 会员tokenString TOKEN_MEMBER = "TOKEN_MEMBER";// 支付tokenString TOKEN_PAY = "TOKEN_pay";// 支付成功String PAY_SUCCESS = "success";// 支付白String PAY_FAIL = "fail";// 用户有效期 90天Long TOKEN_MEMBER_TIME = (long) (60 * 60 * 24 * 90);int COOKIE_TOKEN_MEMBER_TIME = (60 * 60 * 24 * 90);Long PAY_TOKEN_MEMBER_TIME = (long) (60 * 15);// cookie 会员 totoken 名称String COOKIE_MEMBER_TOKEN = "cookie_member_token";}
package com.learn.utils;import java.io.IOException;import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;import com.alibaba.fastjson.JSONObject;/*** HttpClient4.3工具类* * @author hang.luo*/
public class HttpClientUtils {private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class); // 日志记录private static RequestConfig requestConfig = null;static {// 设置请求和传输超时时间requestConfig = RequestConfig.custom().setSocketTimeout(2000).setConnectTimeout(2000).build();}/*** post请求传输json参数* * @param url*            url地址* @param json*            参数* @return*/public static JSONObject httpPost(String url, JSONObject jsonParam) {// post请求返回结果CloseableHttpClient httpClient = HttpClients.createDefault();JSONObject jsonResult = null;HttpPost httpPost = new HttpPost(url);// 设置请求和传输超时时间httpPost.setConfig(requestConfig);try {if (null != jsonParam) {// 解决中文乱码问题StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");entity.setContentEncoding("UTF-8");entity.setContentType("application/json");httpPost.setEntity(entity);}CloseableHttpResponse result = httpClient.execute(httpPost);// 请求发送成功,并得到响应if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {String str = "";try {// 读取服务器返回过来的json字符串数据str = EntityUtils.toString(result.getEntity(), "utf-8");// 把json字符串转换成json对象jsonResult = JSONObject.parseObject(str);} catch (Exception e) {logger.error("post请求提交失败:" + url, e);}}} catch (IOException e) {logger.error("post请求提交失败:" + url, e);} finally {httpPost.releaseConnection();}return jsonResult;}/*** post请求传输String参数 例如:name=Jack&sex=1&type=2* Content-type:application/x-www-form-urlencoded* * @param url*            url地址* @param strParam*            参数* @return*/public static JSONObject httpPost(String url, String strParam) {// post请求返回结果CloseableHttpClient httpClient = HttpClients.createDefault();JSONObject jsonResult = null;HttpPost httpPost = new HttpPost(url);httpPost.setConfig(requestConfig);try {if (null != strParam) {// 解决中文乱码问题StringEntity entity = new StringEntity(strParam, "utf-8");entity.setContentEncoding("UTF-8");entity.setContentType("application/x-www-form-urlencoded");httpPost.setEntity(entity);}CloseableHttpResponse result = httpClient.execute(httpPost);// 请求发送成功,并得到响应if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {String str = "";try {// 读取服务器返回过来的json字符串数据str = EntityUtils.toString(result.getEntity(), "utf-8");// 把json字符串转换成json对象jsonResult = JSONObject.parseObject(str);} catch (Exception e) {logger.error("post请求提交失败:" + url, e);}}} catch (IOException e) {logger.error("post请求提交失败:" + url, e);} finally {httpPost.releaseConnection();}return jsonResult;}/*** 发送get请求* * @param url*            路径* @return*/public static JSONObject httpGet(String url) {// get请求返回结果JSONObject jsonResult = null;CloseableHttpClient client = HttpClients.createDefault();// 发送get请求HttpGet request = new HttpGet(url);request.setConfig(requestConfig);try {CloseableHttpResponse response = client.execute(request);// 请求发送成功,并得到响应if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {// 读取服务器返回过来的json字符串数据HttpEntity entity = response.getEntity();String strResult = EntityUtils.toString(entity, "utf-8");// 把json字符串转换成json对象jsonResult = JSONObject.parseObject(strResult);} else {logger.error("get请求提交失败:" + url);}} catch (IOException e) {logger.error("get请求提交失败:" + url, e);} finally {request.releaseConnection();}return jsonResult;}}
package com.learn.utils;import java.net.URLEncoder;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class WeiXinUtils {@Value("${appid}")private String appId;@Value("${secret}")private String secret;@Value("${redirecturi}")private String redirectUri;@Value("${authorizedUrl}")private String authorizedUrl;@Value("${access_token}")private String accessToken;@Value("${userinfo}")private String userinfo;public String getAuthorizedUrl() {return authorizedUrl.replace("APPID", appId).replace("REDIRECT_URI", URLEncoder.encode(redirectUri));}public String getAccessTokenUrl(String code) {return accessToken.replace("APPID", appId).replace("SECRET", secret).replace("CODE", code);}public String getUserInfo(String accessToken, String openId) {return userinfo.replace("ACCESS_TOKEN", accessToken).replace("OPENID", openId);}}
package com.learn.oauth;import javax.servlet.http.HttpServletRequest;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import com.alibaba.fastjson.JSONObject;
import com.learn.base.BaseApiService;
import com.learn.utils.HttpClientUtils;
import com.learn.utils.WeiXinUtils;@Controller
public class OauthController extends BaseApiService {@Autowiredprivate WeiXinUtils weiXinUtils;private String errorPage = "errorPage";// 生成授权链接@RequestMapping("/authorizedUrl")public String authorizedUrl() {String authorizedUrl = weiXinUtils.getAuthorizedUrl();System.out.println("authorizedUrl:" + authorizedUrl);return "redirect:" + weiXinUtils.getAuthorizedUrl();}// 微信授权回调地址@RequestMapping("/callback")public String callback(String code, HttpServletRequest request) {// 1.使用Code 获取 access_tokenString accessTokenUrl = weiXinUtils.getAccessTokenUrl(code);JSONObject resultAccessToken = HttpClientUtils.httpGet(accessTokenUrl);boolean containsKey = resultAccessToken.containsKey("errcode");if (containsKey) {request.setAttribute("errorMsg", "系统错误!");return errorPage;}// 2.使用access_token获取用户信息String accessToken = resultAccessToken.getString("access_token");String openid = resultAccessToken.getString("openid");// 3.拉取用户信息(需scope为 snsapi_userinfo)String userInfoUrl = weiXinUtils.getUserInfo(accessToken, openid);JSONObject userInfoResult = HttpClientUtils.httpGet(userInfoUrl);System.out.println("userInfoResult:" + userInfoResult);request.setAttribute("nickname", userInfoResult.getString("nickname"));request.setAttribute("city", userInfoResult.getString("city"));request.setAttribute("headimgurl", userInfoResult.getString("headimgurl"));return "info";}}
package com.learn;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class AppOauth {public static void main(String[] args) {SpringApplication.run(AppOauth.class, args);}}

准备工作:生成授权链接

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect 若提示该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。

https://open.weixin.qq.com/connect/oauth2/authorize?appid= wx5c43fde3c9733d9e &redirect_uri=http://127.0.0.1:8080/callback&response_type=code&scope= snsapi_userinfo &state=STATE#wechat_redirect

1 第一步:用户同意授权,获取code

2 第二步:通过code换取网页授权access_token

3 第三步:刷新access_token(如果需要)

4 第四步:拉取用户信息(需scope为 snsapi_userinfo)

5 附:检验授权凭证(access_token)是否有效

互联网API开放平台安全设计-基于OAuth2.0协议方式相关推荐

  1. open api的鉴权以及oauth2.0协议

    2019独角兽企业重金招聘Python工程师标准>>> 这篇文章值得读读 http://blog.arganzheng.me/posts/oauth.html 数据越来越多 数据中心 ...

  2. OAuth2.0协议入门(一):OAuth2.0协议的基本概念以及使用授权码模式(authorization code)实现百度账号登录

    一 OAuth2.0协议的基本概念 (1)OAuth2.0协议 OAuth协议,是一种授权协议,不涉及具体的代码,只是表示一种约定的流程和规范.OAuth协议一般用于用户决定是否把自己在某个服务商上面 ...

  3. B2B2C网上商城开发指南——基于SaaS和淘宝API开放平台

    B2B2C网上商城开发指南--基于SaaS和淘宝API开放平台邢波涛  郭  娟  著 ISBN 978-7-121-12983-4 2011年4月出版 定价:49.00元 16开 388 页 内 容 ...

  4. 微信公众平台开发—利用OAuth2.0获取微信用户基本信息

    1.首先在某微信平台下配置OAuth2.0授权回调页面: 2.通过appid构造url获取微信回传code值(appid可在微信平台下找到) 1).微信不弹出授权页面url: A.code回传到页面w ...

  5. 移动云API开放平台助力开发者驰骋云端

    作者:中国移动云能力中心  --王仁喜 概要:本篇文章带你深入了解移动云API开放平台如何助力开发者驰骋云端. 初识移动云API开放平台 随着移动云业务的不断发展,用户对移动云被集成能力的要求越来越高 ...

  6. 【5】天猫精灵开放平台实验—基于天气查询模板创建开发屏显页面技能

    文章目录 天猫精灵开放平台实验-基于模板创建开发屏显页面技能 一.前提准备 二.登录天猫精灵开放平台 (一)创建新技能 1.创建语音技能 2.填写基本信息 (二)创建后端服务 1.创建后端服务 2.关 ...

  7. 【人工智能 Open AI】通用 API 开放平台的系统架构设计

    写一篇技术文章<通用 API 开放平台的系统架构设计>,分5个章节,细化到三级目录,不少于2000字.使用markdown格式输出. 文章目录 通用 API 开放平台的系统架构设计 一.前 ...

  8. 基于oAuth2.0开发属于自己的SSO授权服务 - 授权码(Authourization Code)模式 (持续更新中。。。)

    此文章篇幅较长,平日上班较少时间写作,请见谅.持续更新中... oAuth2.0系列文章目录 #mermaid-svg-AZMPq56OmFj1I7k0 {font-family:"treb ...

  9. OAuth2.0协议(一) - 授权码许可流程

    OAuth2.0是什么可以拿来做什么,它只认真的做了一件事授权(Authorization).OAuth2.0是 Open Authorization 2.0的简称,既然是2.0那前面肯定有个1.0. ...

最新文章

  1. python 替换字符串的方法replace()、正则re.sub()
  2. Adobe pixel Bender toolkit
  3. 部署Awstats日志分析系统
  4. [YTU]_1064 (输入三个字符串,按由小到大的顺序输出)
  5. mysql在线快速修改密码_MySQL修改密码的几种方式
  6. Java - 文件(IO流)
  7. 浙江大学计算机保研条件_【如何将保研成功率提至100%】来自取得浙大等五所顶尖院校保研资格学长的干货分享(联系导师章节已更)...
  8. Docker-pull
  9. springboot线程池使用
  10. 【实用软件】局域网传输神器-LANDrop
  11. 多个excel工作簿合并_多个excel工作簿合并到一个工作簿中
  12. 博客线下推广的小技巧
  13. 中华第一考----系统架构设计师考试
  14. LOJ 6131 Fiend - 行列式 - 可并堆 - 贪心
  15. PL330 DMAC笔记(1) - 简介
  16. android安卓-开源框架汇总
  17. 苹果三代耳机_P130 【AirPods 3代】绝对性的福利!“地表最强真无线耳机” 苹果第三代AirPods Pro蓝牙耳机、妙不可言!...
  18. K8S 学习笔记三 核心技术 Helm nfs prometheus grafana 高可用集群部署 容器部署流程
  19. matlab实现logit模型/逻辑回归(详细版)
  20. Leakcanary的使用

热门文章

  1. NSUserDefaults的用法(轻量级本地数据存储)
  2. 封装getByClass(JS获取class的方法封装为一个函数)
  3. 基于DSP的汽车减震弹簧故障诊断仪的设计
  4. 【328天】每日项目总结系列066(2017.12.30)
  5. 萌宝出街,熊孩子逆袭小小“时髦精”
  6. 菜鸟教程终极篇之Microsoft Windows Pre-installation Environment (Windows PE) 2.0
  7. 安装Hadoop及Spark(Ubuntu 16.04)
  8. 关于mysql存储大数据的问题
  9. 告别2013拥抱2014
  10. VMware vSphere学习笔记二