精华内容
下载资源
问答
  • Java实现Google第三方登录

    万次阅读 多人点赞 2017-03-28 11:15:52
    其实所有的第三方登录都是基于OAuth协议的,大多数平台都支持OAuth2.0,只有Twitter的是基于OAuth1.0来做的。所以只要弄明白一个,其他的什么qq、微信、微博的第三方登录也都一样。上一篇写的Facebook,现在再写一个...

           其实所有的第三方登录都是基于OAuth协议的,大多数平台都支持OAuth2.0,只有Twitter的是基于OAuth1.0来做的。所以只要弄明白一个,其他的什么qq、微信、微博的第三方登录也都一样。上一篇写的Facebook,现在再写一个Google,两篇都看完的同学就会明白“道理都是相通的”这句话的意思了!

           我做第三方登录的目的仅仅是获取到用户信息,然后将用户信息和本地程序的某一部分绑定,保存到数据库,如果有同学要获取其他的信息,那就获取到accessToken后去找API即可。

    下面依然是demo,只提供思路,代码写的比较简单,都写到一个类中,方便同学理解。

    开发流程:

    1、了解OAuth2.0

    2、到Google官网注册开发者账号,创建凭据(就是应用)

    3、代码实现

    下面逐步介绍

    1、了解OAuth2.0(非常重要)

    因为第三方登录离不开OAuth协议,了解这个是必要的。

    【摘自Google官网】

    注:有英语基础的同学强烈建议看原文,千万不要用Google翻译,翻译完了全是坑,更糊涂!(我的英语不太好,只限于理解但是翻译不出来,所以具体的流程看下面的流程图就可以了,或者看上一篇的facebook的OAuth介绍)



    算了,我还是丢回人吧,大概翻译一下流程(纯人工翻译,可能不准确,但是不会影响你的理解):

    Google的OAuth2.0支持多种语言PHP, Java, Python, Ruby,  ASP.NET.

    这个授权从你的应用重定向到Google的url开始,你请求url时携带的参数要标明你想获取的参数类型。Google来处理用户的身份验证、session、还有用户是否授权,当用户授权成功后Google会给你返回一个授权的code(通过在应用里定义好的回调地址传回code参数),然后你就可以用这code(临时令牌)调Google API来换取access_Token(授权令牌)和refresh_Token(刷新令牌)。

    你的应用需要存储这个refresh_Token(刷新令牌)留着以后你的access_Token(授权令牌过期的时候使用,然后就可以用access_Token(授权令牌来访问Google API 获取用户信息了。

    (我去:翻译完感觉自己不会说人话了,英语不好的同学凑合着看吧,重要的理解下面的流程图)

    2、到Google官网注册开发者账号,创建凭据(就是应用)

    ①登录Google的开发者平台,创建账号  https://developers.google.com/   

    ②创建应用https://console.developers.google.com/apis/credentials

    <1>创建凭据

    创建完成后会看到客户端id和客户端秘钥(妥善保存,代码中要用)

    如果那个重定向的地址没看懂的话往后看代码就理解了,然后定义同意屏幕,是用户授权登录时看到的页面


    到此,应用就创建完成了

    3、代码实现(分为两类同学,分别找对应自己的实现方式)

    【靠自己】想自主实现的同学,我截图具体位置,慢慢摸索同样可以做出来

    登录开发者平台 https://developers.google.com/    然后跟着截图一步一步往下走




    https://developers.google.com/identity/choose-auth


    先照着官网写个页面体验一下,直接复制粘贴就可以https://developers.google.com/identity/sign-in/web/


    体验完之后到guides页面,将基本的四部参照文档完成https://developers.google.com/identity/sign-in/web/devconsole-project


    上面的四步是web页面,下面做后台验证https://developers.google.com/identity/choose-auth



    上面的5步做完之后来这找获取用户信息的API(我做的时候这个接口找的很费劲)


    获取用户信息选这个


    想查询请求url点第二个红框,requestUrl会自动填充(这一步就是想找到获取用户信息的Url,获取到url就可以在后台调用接口了)


    到此,获取到用户信息之后就可以和自己的程序进项绑定了,后面的登录逻辑视业务要求而定。

    【无力者】不想自己找文档,不想思考,着急做的同学,看我上传的代码,复制粘贴就可以了

    ①google.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html lang="en">
    <head>
    <meta name="google-signin-scope" content="profile email">
    <meta name="google-signin-client_id"
    	content='客户端ID'>
    <script src="https://apis.google.com/js/platform.js" async defer></script>
    </head>
    <body>
    	<div class="g-signin2" data-onsuccess="onSignIn"></div>
    	<a href="#" οnclick="signOut();">Sign out</a>
    	<script>
    		function signOut() {
    			var auth2 = gapi.auth2.getAuthInstance();
    			auth2.signOut().then(function() {
    				console.log('User signed out.');
    			});
    		}
    
    		function onSignIn(googleUser) {
    			//跳转到http://gntina.iok.la/sendRedirect(获取用户信息)
    			location.href = "http://gntina.iok.la/sendRedirect";
    			//获取用户基本信息,但是此id不能给后台用,不安全,改用id_token
    			/*从这往下的代码都不需要,因为是在后台验证,后台获取用户信息
                            var profile = googleUser.getBasicProfile();
    			console.log('google自己封装好的获取用户信息');
    			console.log('ID: ' + profile.getId()); // Do not send to your backend! Use an ID token instead.
    			console.log('Name: ' + profile.getName());
    			console.log('Image URL: ' + profile.getImageUrl());
    			console.log('Email: ' + profile.getEmail()); // This is null if the 'email' scope is not present.
    			
    			//将id_token发送给后台进行验证
    			var id_token = googleUser.getAuthResponse().id_token;
    			var xhr = new XMLHttpRequest();
    			xhr.open('POST', 'http://gntina.iok.la/idToken');
    			xhr.setRequestHeader('Content-Type',
    					'application/x-www-form-urlencoded');
    			xhr.onload = function() {
    				console.log('Signed in as: ' + xhr.responseText);
    			};
    			xhr.send('idtoken=' + id_token);
                           */
                    }
    	</script>
    </body>
    </html>
    ②controller

    package com.lenovo.login.controller;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import net.sf.json.JSONObject;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    /**
     * @ClassName: LoginController
     * @Description: Google第三方登录
     * @author gaona
     * @param
     * @date Mar 13, 2017
     */
    @Controller
    public class LoginController {
    
    	private static String client_id = "客户端id";
    	private static String client_secret = "客户端秘钥";
    	private static String scope = "https://www.googleapis.com/auth/drive.metadata.readonly";
    	private static String redirect_url = "http://gntina.iok.la/GoogleUserInfo";
    	private static String code_url = "https://accounts.google.com/o/oauth2/v2/auth";
    	private static String token_url = "https://www.googleapis.com/oauth2/v4/token";
    	private static String user_url = "https://www.googleapis.com/oauth2/v2/userinfo";
    	private static String verify_url = "https://www.googleapis.com/oauth2/v3/tokeninfo";
    
    	//第一步:跳转到登录页面
            @RequestMapping(value = "/login")
    	public String toIndex(HttpServletRequest request) {
    		return "google";
    	}
    
    	/**
    	 * @Title: Login
    	 * @Description: google登录验证后会重定向到此地址,并附带访问授权码,不能为公开的ip地址
    	 * @author 此方法是用带回的code换取accessToken,然后用accessToken换取用户信息,这个地址就是在创建应用时定义的重定向地址
    	 * @return Object
    	 * @date Mar 23, 2017 10:37:38 AM
    	 * @throws
    	 */
    	@RequestMapping(value = "/GoogleUserInfo")
    	@ResponseBody
    	public static Object Login(HttpServletRequest request) {
    		String code = request.getParameter("code");
    		System.out.println(code);
    		
    //		String idToken = getGoogleAccessToken(code);
    //		System.out.println(idToken);
    //		JSONObject verifyToken = verifyToken(idToken);
    //		System.out.println(verifyToken);
    		
    		String accessToken = getGoogleAccessToken(code);
    		System.out.println(accessToken);
    		JSONObject userInfo = getUserInfo(accessToken);
    		System.out.println(userInfo);
    		return userInfo;
    	}
    
    	/**
    	 * @throws Exception
    	 * @throws IOException
    	 * @Title: sendRedirect
    	 * @Description:发送授权请求
    	 * @author 第二步,在google.jsp中用户登录成功以后回跳转到这个路径,发送请求让用户授权,授权成功后重定向到/GoogleUserInfo,也就是创建应用时定义的重定向地址
    	 * @return String
    	 * @date Mar 24, 2017 3:11:36 PM
    	 * @throws
    	 */
    	@RequestMapping(value = "/sendRedirect")
    	public void sendRedirect(HttpServletResponse response) throws Exception {
    		// 随机字符串,防止csrf攻击
    		String state = UUID.randomUUID() + "";
    		Map<String, String> params = new HashMap<String, String>();
    		params.put("client_id", client_id);
    		params.put("redirect_uri", redirect_url);
    		params.put("response_type", "code");
    		params.put("scope", scope);
    		params.put("access_type", "offline");
    		params.put("state", state);
    		params.put("include_granted_scopes", "true");
    		String url = HttpClientUtil.getUrl(code_url, params);
    		response.sendRedirect(url);
    	}
    
    	/**
    	 * @Title: getGoogleAccessToken
    	 * @Description: 获取accessToken
    	 * @author 第三步,用重定向带回来的code换取accessToken
    	 * @return String
    	 * @date Mar 25, 2017 10:25:00 AM
    	 * @throws
    	 */
    	public static String getGoogleAccessToken(String code) {
    		HashMap<String, String> params = new HashMap<String, String>();
    		params.put("client_id", client_id);
    		params.put("redirect_uri", redirect_url);
    		params.put("client_secret", client_secret);
    		params.put("grant_type", "authorization_code");
    		params.put("code", code);
    		String[] responseResult = null;
    		String accessToken =null;
    		String idToken=null;
    		try {
    			responseResult = HttpClientUtil.getStringByPost(token_url, params,
    					null);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		if (null != responseResult && responseResult[0].equals("200")) {
    			String result = responseResult[1];
    			 JSONObject jsonObject = JSONObject.fromObject(result);
    			 accessToken = jsonObject.getString("access_token");
    			 idToken=jsonObject.getString("id_token");
    		}
    		return accessToken;
    //		return idToken;
    	}
    
    	/**
    	 * @Title: getUserInfo
    	 * @Description: 获取用户信息
    	 * @author第四步,用accessToken获取用户信息
    	 * @return String
    	 * @date Mar 25, 2017 11:50:23 AM
    	 * @throws
    	 */
    	public static JSONObject getUserInfo(String accessToken) {
    		HashMap<String, String> params = new HashMap<String,String>();
    		params.put("access_token", accessToken);
    		String[] responseResult =null;
    		JSONObject userInfo=null;
    		try {
    			responseResult = HttpClientUtil.getStringByGet(user_url, params);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		if (null != responseResult && responseResult[0].equals("200")) {
    			String result = responseResult[1];
    			userInfo =  JSONObject.fromObject(result);   
    		}
    		return userInfo;
    	}
    	
    	/**
    	 * @Title: verifyToken  
    	 * @Description:验证用户token是否是来自本应用的请求,校验aud和clientID是否相同  
    	 * @author第五步,验证用户是否来自你的应用,防刷,根据需要加到逻辑里
    	 * @return String
    	 * @date Mar 25, 2017 7:36:33 PM
    	 * @throws
    	 */
    	public static JSONObject verifyToken(String idToken){
    		HashMap<String, String> params = new HashMap<String,String>();
    		params.put("id_token", idToken);
    		String[] responseResult =null;
    		JSONObject verifyInfo=null;
    		try {
    			responseResult = HttpClientUtil.getStringByGet(verify_url, params);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		if (null != responseResult && responseResult[0].equals("200")) {
    			String result = responseResult[1];
    			verifyInfo =  JSONObject.fromObject(result);   
    		}
    		return verifyInfo;
    	}
    
    }
    
    流程明白了以后代码就简单了,实际上一共就3个接口,接口调用的方式用的http

    ③httpClienUtil(没有截取全,只是部分代码供参考,怕同学们因为调接口看晕了)

    /**
         * 返回结果说明:
         * String[] result
         * result[0] = responseCode 
         * result[1] = responseBody
         * @param url
         * @param params
         * @return UTF-8
         * @throws Exception
         */
    	public String[] getByUtf(String url, Map<String, String>params) throws Exception {
    		if(params != null){
    			StringBuffer buf = new StringBuffer();
    			for(String key : params.keySet()){
    				buf.append(key);
    				buf.append("=");
    				buf.append(URLEncoder.encode(params.get(key),"UTF-8"));
    				buf.append("&");
    			}
    			String bufStr = buf.toString();
    			if(StringUtils.isNotEmpty(bufStr)){
    				String param = bufStr.substring(0, bufStr.lastIndexOf("&"));
    				if (-1 == url.indexOf("?")) {
    					url += "?" + param;
    				} else {
    					url += "&" + param;
    				}
    			}
    		}
    		GetMethod getmethod = new GetMethod(url);
            getmethod.getParams().setContentCharset(UTF_CHARSET);
    		return httpRequest(getmethod,UTF_CHARSET);
    
    	}
    

    希望可以帮助到有需要的同学,有些东西了解个大概就往下走,不要深入,不然很容易陷进去出不来,我就是不幸的那个,陷进去出不来,出来了之后才发现看了一些没用的浪费时间。

    =====================================补充========================================

    直接调用googleSDK的方式更简单,直接上代码:

    google.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
      <head>
        <meta name="google-signin-scope" content="profile email">
        <meta name="google-signin-client_id" content="应用编号">
        <script src="https://apis.google.com/js/platform.js" async defer></script>
      </head>
      <body>
        <div class="g-signin2" data-onsuccess="onSignIn" data-theme="dark"></div>
        <a href="#" οnclick="signOut();">Sign out</a>
        
        <script>
          function onSignIn(googleUser) {
            // 客户端如果有需要的话可以通过profile来获取用户信息
            var profile = googleUser.getBasicProfile();
            // 传回后台验证,并获取userid
            var id_token = googleUser.getAuthResponse().id_token;
            console.log("ID Token: " + id_token);
            var xhr = new XMLHttpRequest();
            xhr.open('POST', 'http://gntina.iok.la/googleVerify');
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.onload = function() {
              console.log('Signed in as: ' + xhr.responseText);
            };
            xhr.send('idtokenstr=' + id_token);
          };
          
          function signOut() {
        	    var auth2 = gapi.auth2.getAuthInstance();
        	    auth2.signOut().then(function () {
        	      console.log('User signed out.');
        	    });
        	  }
        </script>
      </body>
    </html>
    Controller:验证,获取用户信息

    @RequestMapping(value = "/googleVerify", method = RequestMethod.POST)
    	public void verifyToken(String idtokenstr) {
    		System.out.println(idtokenstr);
    		GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(
    				new NetHttpTransport(), JacksonFactory.getDefaultInstance())
    				.setAudience(Collections.singletonList(client_id)).build();
    		GoogleIdToken idToken = null;
    		try {
    			idToken = verifier.verify(idtokenstr);
    		} catch (GeneralSecurityException e) {
    			System.out.println("验证时出现GeneralSecurityException异常");
    		} catch (IOException e) {
    			System.out.println("验证时出现IOException异常");
    		}
    		if (idToken != null) {
    			System.out.println("验证成功.");
    			Payload payload = idToken.getPayload();
    			String userId = payload.getSubject();
    //			System.out.println("User ID: " + userId);
    //			String email = payload.getEmail();
    //			boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
    //			String name = (String) payload.get("name");
    //			String pictureUrl = (String) payload.get("picture");
    //			String locale = (String) payload.get("locale");
    //			String familyName = (String) payload.get("family_name");
    //			String givenName = (String) payload.get("given_name");
    		} else {
    			System.out.println("Invalid ID token.");
    		}
    	}



    展开全文
  • 扫盲:Java 后端开发常用的 10 种第三方服务

    千次阅读 多人点赞 2020-09-11 14:19:08
    从此第三方服务不再迷茫。

    严格意义上说,所有软件的第三方服务都可以自己开发,不过从零到一是需要时间和金钱成本的。就像我们研发芯片,投入了巨大的成本,但仍然没有取得理想的成绩,有些事情并不是一朝一夕,投机取巧就能完成的。

    请肆无忌惮地点赞吧,微信搜索【沉默王二】关注这个在九朝古都洛阳苟且偷生的程序员。

    本文 GitHub github.com/itwanger 已收录,里面还有我精心为你准备的一线大厂面试题。

    Java 后端开发通常会涉及到很多第三方服务,那么都有哪些成熟的方案可供直接上手使用呢?

    1)IaaS

    IaaS 的英文全称是 Infrastructure as a Service,即基础设施服务,指把 IT 基础设施作为一种服务通过网络对外提供,并根据用户对资源的实际使用量或占用量进行计费的一种服务模式。IaaS 可根据需求快速纵向扩缩,用户无需购买和管理自己的实体服务器和其他数据中心基础结构,从而避免了相应的开支和复杂操作。

    用户通过 IaaS 可以完成的典型事项包括:

    • 测试和开发。
    • 网站托管。
    • 存储、备份和恢复。
    • Web 应用。
    • 高性能计算。
    • 大数据分析。

    基本上所有的云服务商都提供了 IaaS 服务,国内最强大的云服务商当属阿里云。

    2)PaaS

    PaaS 的英文全称是 Platform as a Service,只需要提交代码到指定运行环境,代码打包、部署、IP 绑定都由平台完成。

    与 IaaS 相比,用户不需要管理与控制云端基础设施(包含网络、服务器、操作系统或存储),但需要控制上层的应用程序部署与应用托管的环境。

    3)SaaS

    SaaS 的英文全称是 Software as a Service,用户在这种模式下,不需要经过传统的安装步骤就可以通过网络使用软件。SaaS 最大的特色在于软件本身并没有被下载到用户的硬盘,而是存储在提供商的云端或者服务器。

    怎么区分 IaaS、PaaS 和 SaaS 呢?来看下面这张图。

    如果我们开发了一个网站,按照传统的方式,我们需要买专业的服务器(连接网络),并在上面安装服务器软件,然后再把编写好的网站部署上去。

    如果采用 IaaS 服务的话,就不需要自己购买服务器了,直接在租用的云服务器上安装服务器软件并且部署网站即可。

    如果采用 PaaS 服务的话,不需要购买服务器,也不需要安装服务器软件,只需要部署网站即可。

    如果采用 SaaS 服务的话,网站也不需要自己开发了,直接使用服务商开发好的网站,后期的升级、维护都交由服务商来负责。

    阮一峰的网络日志上这样解释三者之间的关系。假如你想做披萨生意,有三种方案。

    方案一,IaaS。

    他人提供厨房、炉子、煤气,你使用这些基础设施,来烤你的披萨。

    方案二,PaaS。

    除了基础设施,他人还提供披萨饼皮。你只需要把自己的配料洒在饼皮上,至于是牛肉味的还是奥尔良鸡翅味的,你来决定。

    方案三,SaaS。

    他人直接做好了披萨,你拿到手就是一个成品。你要做的就是把披萨卖出去,最好印上自己的 Logo。

    4)域名

    有了可以提供服务的应用后,还需要一个能够让人记得住的域名,最好越简单越好。拿维基百科来说,wikipedia.org 是一个域名,和 IP 地址 208.80.152.2 相对应,用户可以直接访问 wikipedia.org 来代替 IP 地址,域名系统(DNS)会将域名转化成便于机器识别的 IP 地址。

    有一段时间,域名炒得很厉害,就像炒楼盘一样。我有个大学同学就屯了不少域名,不过最终都没有卖出去。

    小米联合创始人黎万强之前在微博上确认了小米域名(mi.com)的交易价格,360 万美元,约合人民币 2243 万元左右。雷军直呼“贼贵”!

    我是通过腾讯云买的域名。

    http://www.itwanger.com/

    it 即 information technology,wanger 就是“沉默王二”中“王二”的拼音。不过说真的,后悔买 .com 了,年费有点贵,应该换成冷门的域名,比如说 .top,太穷了我。

    5)CDN

    CDN 的全称是 Content Delivery Network,即内容分发网络,一种透过互联网互相连接的电脑网络系统,利用最靠近每位用户的服务器,更快、更可靠地将音乐、图片、影片、应用程序及其他文件发送给用户,来提供高性能、可扩展性及低成本的网络内容传递给用户。

    比较有名的 CDN 服务商有:

    • Cloudflare,提供的免费版解决方案足以保护小网站免受 DDoS 之灾,也可以隐藏网站的真实 IP 地址。在海外有着极好的响应速度,国内好像不咋滴。

    • 腾讯云,资源储备遍布全球 50+ 国家与地区,全网带宽 120Tbps+。国内 1100+ 加速节点,覆盖移动、联通、电信及十几家中小型运营商。

    • 阿里云,全球 2800+ 节点,130T 带宽能力,六大洲覆盖,国内主流运营商支持。

    • 七牛云,全球 2000 节点,20+ 运营商覆盖,访问提速 80%,应用场景包括音视频点播、大文件下载、Web 加速服务等。

    • 又拍云,全球 1100+ 节点,10Tbps 带宽储备,国内主流运营商支持。

    我个人在做网站的时候,喜欢用 BootCDN 来加速 CSS 和 JavaScript,记忆里简介上说是又拍云和 Bootstrap 中文网合作的,现在看是猫云——不知道发生了什么。

    6)邮件发送

    基本上每个应用都离不开邮件发送,最常用的邮件服务器就是腾讯邮箱和网易邮箱。常用的电子邮件协议包括 SMTP、POP3 和 IMAP,不过,邮件的创建和发送只需要用到 SMTP 协议就可以了。

    Java 官方提供了对电子邮件协议封装的 Java 类库,就是 JavaMail,但并没有包含在标准的 JDK 中,GitHub 地址如下:

    https://javaee.github.io/javamail/

    记得之前接到过这样一个需求,要求发送的邮件不能到垃圾邮箱里,还挺难做的。因为邮件服务器,比如说腾讯和网易,都做了邮件的过滤器,会识别一些邮件,自动放到垃圾邮箱里。

    7)短信发送

    使用短信发送验证码几乎是每个应用必不可少的一部分,仿佛手机号码就代表了一个人,所以丢手机是一件非常危险的事情——需要立即挂失。

    短信是需要运营商支持的,所以基本上都需要依赖第三方代理。市面上有很多短信网关代理,阿里云通信是比较常用的一个,以前叫阿里大于。

    阿里云通信的价格是每条短信 0.036 元,市面上还有一些其他的服务商,有些价格更低,但稳定性我个人没有测评过。我的技术交流群里就潜藏了不少做短信的商户人员。

    应用接入阿里云通信并不复杂,我之前在 CSDN 上分享过一个博客,很详细,图文并茂,还带源码实例,需要的小伙伴可以去围观下。

    https://qingmiaogu.blog.csdn.net/article/details/78751698

    8)消息推送

    消息推送(Push)指运营人员通过自己的产品或第三方工具对用户移动设备进行的主动消息推送。用户可以在移动设备锁定屏幕和通知栏看到 push 消息通知,通知栏点击可唤起 APP 并去往相应页面。

    移动应用上,推送已经成为一个标配功能。

    iOS 在系统层面与苹果 APNs(Apple Push Notification service)服务器建立连接,应用通过观察者模式向 iOS 系统注册关注的消息,系统收到 APNs Server 消息后转发到相应的应用程序。

    Android 的 C2DM(Android Cloud to Device Messaging)采取与 iOS 类似的机制,都是由系统层面来支持消息推送,但是由于 Google 的服务在国内不能稳定的访问,此方案对于国内用户来说基本是无法使用的。

    鉴于 Android 平台 C2DM 推送的不可用性,国内涌现出大量的第三方推送服务提供商,目前应用最为广泛的第三方推送服务提供商包括个推、极光、友盟、小米、华为、BAT 等,我之前用个推做过一个小程序的推送 Demo,API 调用起来很简单,感觉还挺好用的。

    消息推送有时候让人很烦,尤其是一些 APP,不停地推,所以我手机上的消息推送权限基本上是关闭状态的——从此世界就安静了。

    9)开放平台

    通过开放平台,可以使用 OAuth 等协议获取用户在第三方平台上的信息以实现第三方平台登录。比如用户想要登录 A 网站,A 网站让用户提供第三方网站的数据,证明自己的身份。获取第三方网站的身份数据,就需要 OAuth 授权。

    国内的微博、微信、QQ 是最常见的第三方登录方式,阿里系的产品可以通过支付宝授权登录,还有一些网站绑定了 GitHub 登录。

    阮一峰的网络日志上有一篇 GitHub OAuth 第三方登录示例教程:

    https://www.ruanyifeng.com/blog/2019/04/github-oauth.html

    10)支付接口

    目前,接入最多的支付接口就是支付宝和微信。

    支付宝提供了当面付、APP 支付、手机网站支付、电脑网站支付等支付接口。

    提供的文档很齐全,还有 Java、PHP、.NET 等版本的 Demo。

    https://opendocs.alipay.com/open/270

    微信支付的话,我推荐使用开源工具库 WxJava:

    https://github.com/Wechat-Group/WxJava

    我们公司的网站就用的这个,支持包括微信支付、开放平台、小程序、企业微信/企业号和公众号等的后端开发,很齐全。

    以上,希望对小伙伴们有所帮助,我们下期见。

    二哥肝了两天两夜,《程序员不可或缺的软实力》第一版强势来袭,纯手敲,足足 20 万字精华文章,贯穿了我十余年的编程生涯,涉及到了生活和工作中的方方面面,如果你是迷茫的在校大学生,或者刚入职的新人,相信我的个人经历,可以给你带去一些思考,从而树立起正确的人生观和价值观。

    那这份 PDF 该怎么获取呢?

    链接:https://pan.baidu.com/s/1TA3txLvHxQNJEOJUHSZEqQ 密码:ps7z

    如链接失效,请转至备用链接:https://shimo.im/docs/pJQv6qVcHqdYwrxx

    最后,真心希望这份 PDF 能够对大家起到实质性的帮助,我也会在后面不断完善这本电子书,敬请期待。

    当然,也日常求个赞!

    展开全文
  • 随着中国互联网的发展,业务... 例如:以前的程序员开发一个邮箱发送的邮件的功能,他可能需要自己搭建一个邮箱服务器(麻烦),而现在的开发者只需要找到邮箱服务提供商(如:阿里云),然后对接他们的服务。   如何...

         随着中国互联网的发展,业务需求越来越复杂 。所有出现了许多做软件服务的公司,如: 阿里云、百度云、新浪、微信等等公司都推出了一系列的产品服务。这样给了小型公司带来福音。让开发者把精力放在了需求上面。

         例如:以前的程序员开发一个邮箱发送的邮件的功能,他可能需要自己搭建一个邮箱服务器(麻烦),而现在的开发者只需要找到邮箱服务提供商(如:阿里云),然后对接他们的服务。

     

    如何调用调用第三方接口( 本文案例:百度云文本审核)

    百度云AI 接口地址

    1.找到你需要调用的服务

    2.选择使用

    3.创建应用,获取调用接口的参数 ( 这里是 API Key ,Sercert Key ,其他服务商大致差不多)

    4.找到接入文档

    5.找到接口地址以及请求参数

    这里content 参数是我们提供的需要审核的内容,access_token 是调用百度API的凭证

    6.获取access_token

    点击进去copy 获取access_token 的Java 代码

    package com.baidu.ai.api.auth;
    
    import org.json.JSONObject;
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.util.List;
    import java.util.Map;
    /**
     * @作者: tjx
     * @描述:  获取access_token
     * @创建时间: 创建于17:11 2018/9/7
     **/
    public class AuthService {
    
        /**
         * 获取权限token
         * @return 返回示例:
         * {
         * "access_token": "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567",
         * "expires_in": 2592000
         * }
         */
        public static String getAuth() {
            // 官网获取的 API Key 更新为你注册的
            String clientId = "百度云应用的AK";
            // 官网获取的 Secret Key 更新为你注册的
            String clientSecret = "百度云应用的SK";
            return getAuth(clientId, clientSecret);
        }
    
        /**
         * 获取API访问token
         * 该token有一定的有效期,需要自行管理,当失效时需重新获取.
         * @param ak - 百度云官网获取的 API Key
         * @param sk - 百度云官网获取的 Securet Key
         * @return assess_token 示例:
         * "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567"
         */
        public static String getAuth(String ak, String sk) {
            // 获取token地址
            String authHost = "https://aip.baidubce.com/oauth/2.0/token?";
            String getAccessTokenUrl = authHost
                    // 1. grant_type为固定参数
                    + "grant_type=client_credentials"
                    // 2. 官网获取的 API Key
                    + "&client_id=" + ak
                    // 3. 官网获取的 Secret Key
                    + "&client_secret=" + sk;
            try {
                URL realUrl = new URL(getAccessTokenUrl);
                // 打开和URL之间的连接
                HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
                connection.setRequestMethod("GET");
                connection.connect();
                // 获取所有响应头字段
                Map<String, List<String>> map = connection.getHeaderFields();
                // 遍历所有的响应头字段
                for (String key : map.keySet()) {
                    System.err.println(key + "--->" + map.get(key));
                }
                // 定义 BufferedReader输入流来读取URL的响应
                BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String result = "";
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
                /**
                 * 返回结果示例
                 */
                System.err.println("result:" + result);
                JSONObject jsonObject = new JSONObject(result);
                String access_token = jsonObject.getString("access_token");
                return access_token;
            } catch (Exception e) {
                System.err.printf("获取token失败!");
                e.printStackTrace(System.err);
            }
            return null;
        }
    
    
    }
    

    把创建时候获取的两个参数填进去调试下

    7.封装API

     7.1 封装结果Bean

    /**
     * Copyright 2018 bejson.com
     */
    package com.baidu.ai.api.pojo;
    import java.util.List;
    
    /**
     * Auto-generated: 2018-09-07 17:28:44
     *
     * @author bejson.com (i@bejson.com)
     * @website http://www.bejson.com/java2pojo/
     */
    public class Pass {
    
        private double score;
        private List<String> hit;
        private int label;
        public void setScore(double score) {
            this.score = score;
        }
        public double getScore() {
            return score;
        }
    
        public void setHit(List<String> hit) {
            this.hit = hit;
        }
        public List<String> getHit() {
            return hit;
        }
    
        public void setLabel(int label) {
            this.label = label;
        }
        public int getLabel() {
            return label;
        }
    
    }
    /**
     * Copyright 2018 bejson.com
     */
    package com.baidu.ai.api.pojo;
    import java.util.List;
    
    /**
     * Auto-generated: 2018-09-07 17:28:44
     *
     * @author bejson.com (i@bejson.com)
     * @website http://www.bejson.com/java2pojo/
     */
    public class Result {
    
        private int spam;
        private List<String> review;
        private List<String> reject;
        private List<Pass> pass;
        public void setSpam(int spam) {
            this.spam = spam;
        }
        public int getSpam() {
            return spam;
        }
    
        public void setReview(List<String> review) {
            this.review = review;
        }
        public List<String> getReview() {
            return review;
        }
    
        public void setReject(List<String> reject) {
            this.reject = reject;
        }
        public List<String> getReject() {
            return reject;
        }
    
        public void setPass(List<Pass> pass) {
            this.pass = pass;
        }
        public List<Pass> getPass() {
            return pass;
        }
    
    }
    /**
     * Copyright 2018 bejson.com
     */
    package com.baidu.ai.api.pojo;
    
    /**
     * Auto-generated: 2018-09-07 17:28:44
     *
     * @author bejson.com (i@bejson.com)
     * @website http://www.bejson.com/java2pojo/
     */
    public class CheckTextResult {
    
        private long log_id;
        private Result result;
        public void setLog_id(long log_id) {
            this.log_id = log_id;
        }
        public long getLog_id() {
            return log_id;
        }
    
        public void setResult(Result result) {
            this.result = result;
        }
        public Result getResult() {
            return result;
        }
    
    }

      7.2 封装HttpClient

    package com.utis;
    
    import java.io.IOException;
    import java.net.URI;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    import org.apache.http.NameValuePair;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    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.client.utils.URIBuilder;
    import org.apache.http.entity.ContentType;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.message.BasicNameValuePair;
    import org.apache.http.util.EntityUtils;
    /**
     * @作者: tjx
     * @描述:  http请求
     * @创建时间: 创建于16:37 2018/9/7
     **/
    public class HttpUtil {
    
        public static String doGet(String url, Map<String, String> param) {
            // 创建Httpclient对象
            CloseableHttpClient httpclient = HttpClients.createDefault();
            String resultString = "";
            CloseableHttpResponse response = null;
            try {
                // 创建uri
                URIBuilder builder = new URIBuilder(url);
                if (param != null) {
                    for (String key : param.keySet()) {
                        builder.addParameter(key, param.get(key));
                    }
                }
                URI uri = builder.build();
    
                // 创建http GET请求
                HttpGet httpGet = new HttpGet(uri);
    
                // 执行请求
                response = httpclient.execute(httpGet);
                // 判断返回状态是否为200
                if (response.getStatusLine().getStatusCode() == 200) {
                    resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    if (response != null) {
                        response.close();
                    }
                    httpclient.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return resultString;
        }
    
        public static String doGet(String url) {
            return doGet(url, null);
        }
    
        public static String doPost(String url, Map<String, String> param) {
            // 创建Httpclient对象
            CloseableHttpClient httpClient = HttpClients.createDefault();
            CloseableHttpResponse response = null;
            String resultString = "";
            try {
                // 创建Http Post请求
                HttpPost httpPost = new HttpPost(url);
                // 创建参数列表
                if (param != null) {
                    List<NameValuePair> paramList = new ArrayList<>();
                    for (String key : param.keySet()) {
                        paramList.add(new BasicNameValuePair(key, param.get(key)));
                    }
                    // 模拟表单
                    UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "utf-8");
                    httpPost.setEntity(entity);
                }
                // 执行http请求
                response = httpClient.execute(httpPost);
                resultString = EntityUtils.toString(response.getEntity(), "utf-8");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return resultString;
        }
    
        public static String doPost(String url) {
            return doPost(url, null);
        }
    
        /**
         * 请求的参数类型为json
         * @param url
         * @param json
         * @return
         * {username:"",pass:""}
         */
        public static String doPostJson(String url, String json) {
            // 创建Httpclient对象
            CloseableHttpClient httpClient = HttpClients.createDefault();
            CloseableHttpResponse response = null;
            String resultString = "";
            try {
                // 创建Http Post请求
                HttpPost httpPost = new HttpPost(url);
                // 创建请求内容
                StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
                httpPost.setEntity(entity);
                // 执行http请求
                response = httpClient.execute(httpPost);
                resultString = EntityUtils.toString(response.getEntity(), "utf-8");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    response.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return resultString;
        }
    
    }
    

    7.3封装调用接口

    package com.baidu.ai.api;
    
    import com.baidu.ai.api.pojo.CheckTextResult;
    import com.baidu.ai.api.pojo.Pass;
    import com.baidu.ai.api.pojo.Result;
    import com.utis.HttpUtil;
    import net.sf.json.JSONObject;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * @作者: tjx
     * @描述: 文本审核API
     * @创建时间: 创建于17:19 2018/9/7
     **/
    public class CheckTextAPI {
    
        private static final String URL = "https://aip.baidubce.com/rest/2.0/antispam/v2/spam";
    
        /**
         * @param content 需要审核的文本
         *
         * @return true 通过 false 失败
         */
        public boolean check(String content){
    
            //获取access_token
            String access_token = AuthService.getAuth();
            Map<String,String> parameters = new HashMap<>();
            //添加调用参数
            parameters.put("access_token",access_token);
            parameters.put("content",content);
            //调用文本审核接口
            String result = HttpUtil.doPost(URL, parameters);
    
            // JSON转换
            JSONObject jsonObj = JSONObject.fromObject(result);
            Map<String, Class> classMap = new HashMap<String, Class>();
            classMap.put("result",Result.class);
            classMap.put("pass",Pass.class);
            classMap.put("bass",CheckTextResult.class);
            CheckTextResult bean = (CheckTextResult)JSONObject.toBean(jsonObj, CheckTextResult.class, classMap);
            //根据API返回内容处理业务逻辑 (这里简单模拟,)
            if(bean.getResult().getReject().size() + bean.getResult().getReview().size() > 0){
                return false;
            }
            return true;
        }
    
        public static void main(String[] args) {
            System.out.println( new CheckTextAPI().check("你好"));
        }
    }
    

    结果

    市面上的大部分API服务商的接入方式都是这样的。

    展开全文
  • import java.util.Properties; import javax.mail.*; import javax.mail.internet.*; /** * @创建人 liuzhihui * @创建时间 2019/11/4 * @描述 */ public class EmailTest2 { private String from = "xxx@126....

    这里使用126。

    准备工作:
    依赖

            <!--发邮件-->
            <dependency >
                <groupId >javax.mail </groupId >
                <artifactId >mail </artifactId >
                <version >1.4.5 </version >
            </dependency >
            <dependency >
                <groupId >com.sun.mail </groupId >
                <artifactId >javax.mail </artifactId >
                <version >1.5.4 </version >
            </dependency >
    

    获取客户端授权码;

    测试:

    import java.util.Properties;
    import javax.mail.*;
    import javax.mail.internet.*;
    /**
     * @创建人 liuzhihui
     * @创建时间 2019/11/4
     * @描述
     */
    public class EmailTest2 {
        private String from = "xxx@126.com"; // 发件人邮箱地址
        private String user = "xxx@126.com"; // 发件人称号,同邮箱地址
        private String password = "xxx"; // 发件人邮箱客户端授权码
    
        /**
         *
         * @param to
         * @param text
         * @param title
         */
        /* 发送验证信息的邮件 */
        public boolean sendMail(String to, String text, String title) {
            Properties props = new Properties();
            props.setProperty("mail.smtp.host", "smtp.126.com"); // 设置发送邮件的邮件服务器的属性(这里使用网易的smtp服务器)
            props.put("mail.smtp.host", "smtp.126.com"); // 需要经过授权,也就是有户名和密码的校验,这样才能通过验证(一定要有这一条)
            props.put("mail.smtp.auth", "true"); // 用刚刚设置好的props对象构建一个session
            Session session = Session.getDefaultInstance(props); // 有了这句便可以在发送邮件的过程中在console处显示过程信息,供调试使
            // 用(你可以在控制台(console)上看到发送邮件的过程)
            session.setDebug(true); // 用session为参数定义消息对象
            MimeMessage message = new MimeMessage(session); // 加载发件人地址
            try {
                message.setFrom(new InternetAddress(from));
                message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); // 加载收件人地址
                message.setSubject(title); // 加载标题
                Multipart multipart = new MimeMultipart(); // 向multipart对象中添加邮件的各个部分内容,包括文本内容和附件
                BodyPart contentPart = new MimeBodyPart(); // 设置邮件的文本内容
                contentPart.setContent(text, "text/html;charset=utf-8");
                multipart.addBodyPart(contentPart);
                message.setContent(multipart);
                message.saveChanges(); // 保存变化
                Transport transport = session.getTransport("smtp"); // 连接服务器的邮箱
                transport.connect("smtp.126.com", user, password); // 把邮件发送出去
                transport.sendMessage(message, message.getAllRecipients());
                transport.close();
            } catch (MessagingException e) {
                e.printStackTrace();
                return false;
            }
            return true;
        }
    
        public static void main(String[] args) { // 做测试用
            EmailTest2 ds = new EmailTest2();
            ds.sendMail("279023xxx@qq.com", "你好,这是一封测试邮件,无需回复。", "测试邮件");
        }
    
    }
    
    

    需要修改from ,user,password,如果使用的不是126还要修改smtp。

    springboot发邮件:
    https://blog.csdn.net/yeyinglingfeng/article/details/80678489

    展开全文
  • java对接第三方快递---顺丰SDK

    千次阅读 2020-01-10 15:49:18
    背景介绍:APP内商城,需要对接第三方快递,公司本身和顺丰有月结账户合作,故选用顺丰。 开发之前 开始要到丰桥官网注册账号,丰桥会提供客户编码和校验码到你的邮箱;官方有接入教程,没啥可纠结的,一路申请到底...
  • 大家好,我是你们不熟悉的超厂长,每天2--3更,发布java小白教程 微信公众号:程序员PG 今天早上一直在考虑网上的邮箱注册是怎么注册的 一般流程就是你输入你的邮箱和设置你的密码,点击发送后,就会发给你一个...
  • 第三方登录功能的实现

    万次阅读 多人点赞 2017-03-28 17:13:04
    为什么要使用第三方登录:一般稍微作为一个大点的项目,为了提高用户的群体都会做第三方登录(如:QQ,微信,新浪等) 在往下看之前先注册第三方网站的开发者账号,创建应用完成审核。 QQ : QQ开发者平台 微信: 微信...
  • public static final String USERNAME = "发件人邮箱"; public static final String PASSWORD = "邮箱授权码"; public static final String NICKNAME = "邮箱主题"; /** * 发送邮件(成功true、失败false) ...
  • 第三方登录(QQ-Java版)

    千次阅读 2018-07-05 11:38:59
     这没啥可说的,无非就是想利用QQ庞大的用户群体,提高本站流量,达到快速扩充本站用户的效果,当然,无论是QQ登录,还是其它第三方登录方式,这些都是辅助效果,真正的目的还是需要绑定本站用户。 2.第三方登录所遵守的...
  • Java实现Google第三方授权认证---

    千次阅读 2020-05-07 18:07:54
    } /** @return String @throws @Title: getGoogleAccessToken @Description: 获取accessToken @author 第三步,用重定向带回来的code换取accessToken @date Mar 25, 2017 10:25:00 AM */ public String ...
  • 开发好了邮箱功能,经测试人员测试,无法绑定163企业邮箱!!这怎可能?其他邮箱能绑定,163企业邮箱却绑定不了?于是看了163企业邮箱官网http://www.163mailbox.cn/client-outlook-foxmail-settings.html上面的解决...
  • Java对接微信、支付宝、银联第三方支付

    千次阅读 热门讨论 2021-04-07 09:05:38
    //交易类型 JSAPI 公众号支付 NATIVE 扫码支付 APP APP支付 //二步,签名,参数转xml String requestXMl = WXPayUtil.generateSignedXml(paramMap, key, WXPayConstants.SignType.MD5); try { //发送请求(POST)...
  • 以网易邮箱注册为例,可以读取变填充表单数据,这是第三方网页,用最好java相关知识怎么做到,其他语言也可以,![图片说明](https://img-ask.csdn.net/upload/201509/05/1441450701_115581.png)
  • 最近项目新增一个需求:需要收集用户的邮箱信息。但是直接通过GraphRequest.newMeRequest去获取发现返回值为空,通过查阅资料得知facebook获取用户邮箱还需要授权。 授权方式如下 LoginManager.getInstance()....
  • 使用第三方微信登录

    千次阅读 2018-03-28 12:03:16
    这两天了解了下使用微信第三方登录相关问题,这样方便用户登录,不用担心密码...或者在微信公众平台申请一个服务的公众号 两者的区别可以自行百度第三方微信接口登录流程图: 用户首先请求登录第三方应用(app.we...
  • google 谷歌第三方登录(facebook twitter 登录 第三方登录 web 可以参考,如果是oauth2.0协议 流程都是一样的)
  • Java邮箱验证

    2018-11-08 16:10:39
    百度:java mail,点击一个JavaMail API 进去后,点击右侧download 选择jar包 最后把jar包导入项目中 代码测试 package com.test.demo2; import java.util.*; import java.util.Properties; import javax.mail...
  • 第三方库实战系列视频教程B站学习地址: Android第三方开源库系列—热修复框架使用、原理及项目实战 Android第三方开源库系列—插件化框架使用、原理及项目实战 Android第三方开源库系列—Android组件化使用、原理及...
  • 主要为大家详细介绍了Springboot网站第三方登录 ,微信登录,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • SpringBoot项目接入支付宝第三方登录

    千次阅读 2020-05-05 22:32:48
    今年大四毕业,由于新冠肺炎疫情的原因,开学和毕业答辩的时间都进行了推迟,因此有较多的时间对毕设项目做修改和调整,便在项目中接入微信和支付宝的第三方登录。在此需要说明,微信和支付宝的开发者平台大体一致,...
  • 但是不同的第三方登录因为其细节不同还是有很多坑的,今天我们就从完善开发者信息开始一步一步添加微博第三方登录的功能。 注意,需要完成微博的第三方登录功能需要有一个域名以及修改该域名网站的权限,之后审核时...
  • java邮箱验证Email发送

    2014-05-16 17:16:07
    邮箱验证时要用到的Email发送,向第三方邮箱发送请求让其给目的邮箱发送一封邮件
  • 简单介绍如何调用第三方API

    千次阅读 2018-07-16 09:57:44
    今天给大家分享一下,java学习中需要使用的第三方API的调用1.背景介绍API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组...
  • 主要包括邮箱验证码登录,手机验证码登录,第三方社交登录。支持登录失败自定义返回。实现了登出,从tokenStore中移除认证信息,从而实现统一登出。 项目结构 项目主要包括component config handler translator ...
  • 自己在学java过程中,需要将第三方jar包添加到自己项目中的classpath中去,但是网上查了很多教程,也没找到我想要的,我自己琢磨了一下如何利用eclipse导入第三方jar文件。
  • shareSDK实现QQ第三方分享

    千次阅读 2016-08-30 22:38:09
    ShareSDK 集成QQ第三方分享
  • SpringBoot 微信第三方登陆详解

    万次阅读 2021-03-06 10:06:58
    一步 这篇文章只讲三方登陆主要实现步骤,不讲理论 这是详细理论 拿到微信拉取二维码的接口地址 建一个网页 设一个跳转a标签 接口地址 https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 18,989
精华内容 7,595
关键字:

java第三方邮箱

java 订阅