模拟第三方登录开放接口

废话少说,直接上代码。。。

    1.对外提供第三方顶级接口

/**
 * 对外提供第三方接口
 * @author reyco
 * @date 2019年8月9日
 *
 */
public interface DevelopService {
	/**
	 * 重定向授权登录页
	 * @param client_id			id
	 * @param response_type 	默认code
	 * @param redirect_uri		回调地址
	 * @return
	 */
	Result authorize(String client_id,String response_type,String redirect_uri);
	/**
	 * 验证登录,生成token信息
	 * @param username		用户名
	 * @param password		密码
	 * @return
	 */
	Result setToken(String username,String password);
	/**
	 * 生成token信息
	 * @param client_id			id
	 * @param client_secret		key
	 * @param redirect_uri		回调地址
	 * @param code				登录成功返回的code
	 * @param grant_type		默认authorization_code
	 * @return
	 * @throws Exception
	 */
	Result access_token(String client_id,String client_secret,String redirect_uri,String code,String grant_type) throws Exception;
	/**
	 * 生成用户信息
	 * @param access_token token
	 * @return
	 */
	Result get_user_info(String access_token);
}

2.实现类

/**
 * 对外第三方接口实现类
 * @author reyco
 * @date 2019年8月14日
 *
 */
@Service("developService")
public class DevelopServiceImpl implements DevelopService {
	/**
	 *	  第三方绑定运用绑定	 
	 */
	@Autowired
	private ApplicationService applicationService;
	/**
	 * 用户信息
	 */
	@Autowired
	private AccountsService accountsService;
	/**
	 * redis
	 */
	@Autowired
	private RedisTemplate<String, String> redisTemplate;

	@Override
	public Result authorize(String client_id, String response_type, String redirect_uri) {
		Result result = new Result();
		// 1. 非空判断
		if (StringUtils.isBlank(client_id) || StringUtils.isBlank(redirect_uri) || StringUtils.isBlank(response_type)) {
			result.setMsg("参数错误");
			return result;
		}
		// 2. 验证参数
		Application application = applicationService.searchApplication(client_id);
		// 2.1 验证失败
		if (null == application) {
			result.setMsg("应用不存在");
			return result;
		}
		if (!application.getRedirect_uri().equals(redirect_uri)) {
			result.setMsg("回调地址错误");
			return result;
		}
		if (!response_type.equals("code")) {
			result.setMsg("response_type错误");
			return result;
		}
		// 2.2 验证成功
		result.setIsTrue(true);
		return result;
	}

	@Override
	public Result setToken(String username, String password) {
		// 1. 验证登录
		Result result = accountsService.isLogin(username, password);
		if (!result.isTrue()) {
			return result;
		}
		// 2. 获取用户信息
		Accounts accounts = (Accounts) result.getData();
		// 3. 生成token
		String code = UUID.randomUUID().toString().replace("-", "");
		// 	3.1 生成token
		String token = JWTUtils.createJWT(code, "token", JWTUtils.generalSubject(accounts), 1000 * 10 * 60);
		//  3.2 token放入redis,有效时间10分钟
		ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
		opsForValue.set(code, token, 10 * 60, TimeUnit.SECONDS);
		// 4. 响应
		result.setData(code);
		return result;
	}

	@Override
	public Result access_token(String client_id, String client_secret, String redirect_uri, String code,
			String grant_type) throws Exception {
		Result result = new Result();
		// 1. 非空判断
		if (StringUtils.isBlank(code) || StringUtils.isBlank(client_id) || StringUtils.isBlank(redirect_uri)
				|| StringUtils.isBlank(client_secret) || StringUtils.isBlank(grant_type)) {
			result.setMsg(JSONResult.ERROR_PARAMS);
			return result;
		}
		// 2. 获取applicationResult对象
		Result applicationResult = applicationService.getApplication(client_id);
		// 3. 获取applicationResult对象是否成功
		if (!applicationResult.isTrue()) {
			result.setMsg(JSONResult.ERROR_PARAMS);
			return result;
		}
		// 4. 获取applicationResult对象成功后,获取application对象
		Application application = (Application) applicationResult.getData();
		// 参数是否有误
		if (!application.getRedirect_uri().equals(redirect_uri) || !application.getClient_secret().equals(client_secret)
				|| !"authorization_code".equals(grant_type)) {
			result.setMsg(JSONResult.ERROR_PARAMS);
			return result;
		}
		// 5. 验证token
		// 	5.1 token是否存在
		if (!redisTemplate.hasKey(code)) {
			result.setMsg(JSONResult.ERROR_PARAMS);
			return result;
		}
		ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
		// 	5.2 根据code获取token
		String token = opsForValue.get(code);
		// 	5.3 验证token信息
		JWTResult validateJWT = JWTUtils.validateJWT(token);
		// 获取claims信息
		Claims claims = validateJWT.getClaims();
		//	5.4 token是否失效
		// 		失效时间
		Date expirationDate = claims.getExpiration();
		// 		当前时间
		Date nowDate = new Date();
		if (nowDate.after(expirationDate)) {
			result.setMsg("token已失效");
			return result;
		}
		// 6. 生成token信息
		String subject = claims.getSubject();
		//  6.1 获取用户信息
		Accounts accounts = JsonUtils.jsonToPojo(subject, Accounts.class);
		String uid = accounts.getUid();
		//	6.2 token存储对象
		JSONObject tokenObj = new JSONObject();
		long expirationTime = expirationDate.getTime();
		long nowtime = nowDate.getTime();
		// token有效时间
		long expires_in = (expirationTime - nowtime);
		tokenObj.put("access_token", token);
		tokenObj.put("expires_in", "" + expires_in);
		tokenObj.put("remind_in", "1234");
		tokenObj.put("uid", uid);
		result.setData(tokenObj);
		result.setIsTrue(true);
		return result;
	}

	@Override
	public Result get_user_info(String access_token) {
		Result result = new Result();
		try {
			// 1. 非空判断
			if (StringUtils.isBlank(access_token)) {
				result.setMsg(JSONResult.ERROR_PARAMS);
				return result;
			}
			// 2. 验证token信息
			JWTResult validateJWT = JWTUtils.validateJWT(access_token);
			// 2.1  获取claims信息
			Claims claims = validateJWT.getClaims();
			// 2.2 token失效时间
			Date expirationDate = claims.getExpiration();
			// 	     当前时间
			Date nowDate = new Date();
			if (nowDate.after(expirationDate)) {
				result.setMsg("token已失效");
				return result;
			}
			// 获取token主题信息
			String subject = claims.getSubject();
			// 3. 获取用户信息
			Accounts accounts = JsonUtils.jsonToPojo(subject, Accounts.class);
			//	3.1 user存储对象
			JSONObject userInfoObj = new JSONObject();
			userInfoObj.put("nickname", accounts.getNickname());
			userInfoObj.put("scope", "");
			userInfoObj.put("create_at", accounts.getGmtCreate());
			userInfoObj.put("uid", accounts.getUid());
			result.setData(userInfoObj);
			result.setIsTrue(true);
			return result;
		} catch (JSONException e) {
			e.printStackTrace();
		}
		result.setMsg("token无效");
		return result;
	}

}

3.controller

/**y
 * 模拟第三方登录开发接口
 * @author reyco
 * @date 2019年7月26日
 *
 */
@RequestMapping("oauth2")
@Controller
public class DevelopController {
	
	@Autowired
	private DevelopService developService;
	
	/**
	 * 重定向授权登录页
	 * @param client_id       	id
	 * @param response_type		响应类型默认code
	 * @param redirect_uri		第三方回调地址
	 * @param request
	 * @return
	 * @throws IOException
	 */
	@RequestMapping("authorize")
	public String authorize(String client_id,String response_type,String redirect_uri) throws IOException {
		// 验证参数
		Result result = developService.authorize(client_id, response_type, redirect_uri);
		// 验证参数有误
		if(!result.isTrue()) {
			return "../error.html";
		}
		// 验证参数无误,重定向登录页面
		return "../login.html";
	}
	/**
	 * 验证登录,生成token
	 * @param username 		用户名
	 * @param password 		密码
	 * @param redirect_uri  第三方回调地址(建议前端放在请求头中)
	 * @return				
	 */
	@ResponseBody
	@RequestMapping("login")
	public String login(String username,String password,String redirect_uri) {
		// 验证登录,设置token
		Result result = developService.setToken(username, password);
		// 验证登录失败
		if(!result.isTrue()) {
			return JSONResult.failCreate("用户名或密码错误", result.getMsg()).toJSON();
		}
		// 验证登录失败
		String code = (String)result.getData();
		if(!redirect_uri.contains("?")) {
			redirect_uri = redirect_uri+"?code="+code;
		}else {
			redirect_uri = redirect_uri+"&code="+code;
		}
		return JSONResult.create(redirect_uri).toJSON();
	}
	/**
	 * 获取token信息
	 * @param code				登录验证成功返回的code
	 * @param client_id			id
	 * @param client_secret		key
	 * @param grant_type		默认authorization_code
	 * @param redirect_uri		第三方回调地址
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping("access_token")
	public String access_token(String code,String client_id,String client_secret,String grant_type,String redirect_uri,HttpServletRequest request) throws Exception {
		// 生成token信息
		Result accessTokenResult = developService.access_token(client_id,client_secret,redirect_uri, code, grant_type);
		// 失败
		if(!accessTokenResult.isTrue()) {
			return accessTokenResult.getMsg();
		}
		// 成功,响应token
		Object token = accessTokenResult.getData();
		return token.toString();
	}
	/**
	 * 获取用户信息
	 * @param access_token   token
	 * @param request
	 * @return
	 * @throws JSONException
	 */
	@ResponseBody
	@RequestMapping("get_user_info")
	public String get_user_info(String access_token,HttpServletRequest request) throws JSONException {
		// 生成用户信息
		Result get_user_info_result = developService.get_user_info(access_token);
		// 失败
		if(!get_user_info_result.isTrue()) {
			return get_user_info_result.getMsg();
		}
		// 成功,响应用户信息
		Object token = get_user_info_result.getData();
		return token.toString();
	}
}

4.配置文件

#dyw
dyw.id=a5f452dddd19d8ba
dyw.key=6e72a3e8974b44ad8a4de3c14a6abbbc
dyw.authorize_url=http://login.test.com/oauth2/authorize.do
dyw.callback=http://login.test.com/login/callback.do?type=dyw
dyw.get_token_url=http://login.test.com/oauth2/access_token.do
dyw.get_token_info=http://login.test.com/oauth2/get_user_info.do

5.本地web应用对第三方登录的实现

        5.1登录接口:

/**
 * 第三方登录顶级接口
 * 
 * @author reyco
 * @date 2019年7月23日
 *
 */
public interface LoginService {
	/**
	 * 登录 ---返回重定向地址
	 * @return
	 */
	String login()throws Exception;
	/**
	 * 回调地址
	 * @param code         登录成功后返回的code
	 * @param request      参数request
	 * @return
	 * @throws Exception
	 */
	String callback(String code,HttpServletRequest request,HttpServletResponse response) throws Exception;
}

             5.2实现:

@Service("dyw")
public class DYWLoginServiceImpl implements LoginService{
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	private AccountService accountService;
	@Autowired
	private RestTemplate restTemplate;
	@Autowired
	private RedisTemplate<String, Object> redisTemplate;
	
	@Override
	public String login() throws Exception {
		// 回调地址
		String backUrl = PropertiesUtil.getValue("dyw.callback");
		String authorize_url = PropertiesUtil.getValue("dyw.authorize_url");
		// appid
		String dywID = PropertiesUtil.getValue("dyw.id");
		String state = UUID.randomUUID().toString().replaceAll("-", "");
		String url=authorize_url
				+ "?client_id="+dywID
				+ "&response_type=code"
				+ "&redirect_uri="+URLEncoder.encode(backUrl)
				+ "&state="+state;
		return url;
	}

	@Override
	public String callback(String code, HttpServletRequest request, HttpServletResponse response) throws Exception {
		JSONObject accessToken = getAccessToken(code);
		String token = accessToken.getString("access_token");
		JSONObject userInfo = getUserInfo(token);
		String uid = userInfo.getString("uid");
		String nickname = userInfo.getString("nickname");
		boolean flag = accountService.searchCountByPhone(uid);
		if(flag) {
			// 用户信息
			Integer type=Type.DYW;
			Integer integral = 0;
			String phone=uid;
			String name = nickname;
			String password = "e10adc3949ba59abbe56e057f20f883e";
			Integer status = Status.NORMAL;
			Integer gender = 1;
			String desc = "点击修改备注";
			//注册用户
			accountService.register(type, integral, phone, password, name, gender, null, null, status, desc);
		}
		Account account = accountService.getAccount(uid);
		// 获取登录用户
		String loginPhone = account.getPhone();
		// 是否其它客户端已登录---如果已登录则强制退出
		ValueOperations<String, Object> opsForValue = redisTemplate.opsForValue();
		if(redisTemplate.hasKey(loginPhone)) {
			// 判断redis中是否存在该用户key,并获取
			Object phoneValue = opsForValue.get(loginPhone);
			redisTemplate.delete(loginPhone);
			// 判断redis中是否存在cookie
			if(redisTemplate.hasKey(phoneValue.toString())) {
				redisTemplate.delete(phoneValue.toString());
			}
		}
		Integer id = account.getId();
		Integer vipId = account.getVipId();
		// 获取登录ip
		String ip = CusAccessObjectUtil.getIpAddress(request); 
		// 获取登录城市
		String cityName = IPDataUtils.getCityName(ip); 
		String loginName = account.getName();
		User u = new User(id,loginPhone,vipId,ip, cityName, loginName);
		//  生成cookie的key
		String key = UUID.randomUUID().toString().replace("-", "");
		// 保存到redis
		opsForValue.set(key, JsonUtils.objectToJson(u),30*60,TimeUnit.SECONDS);
		opsForValue.set(loginPhone, key,30*60,TimeUnit.SECONDS);
		// 生成cookie
		CookieUtil.setCookie(request, response, "user_token", key, -1);
		return "http://login.test.com/user/index.html";
	}
	/**
	 * 获取token信息
	 * @param code
	 * @return
	 * @throws Exception
	 */
	private JSONObject getAccessToken(String code) throws Exception {
		String dywID = PropertiesUtil.getValue("dyw.id");
		String dywKey = PropertiesUtil.getValue("dyw.key");
		String callback = PropertiesUtil.getValue("dyw.callback");
		String get_token_url = PropertiesUtil.getValue("dyw.get_token_url");
		get_token_url=get_token_url+"?grant_type=authorization_code" + "&client_id="
				+ dywID + "&client_secret=" + dywKey + "&redirect_uri=" + callback + "&code=" + code;
		String tokenObject = restTemplate.getForObject(get_token_url,String.class);
		JSONObject dywTokenObject = new JSONObject(tokenObject);
		logger.info("dyw."+dywTokenObject.toString());
		return dywTokenObject;
	}
	/**
	 * 获取用户信息
	 * @param token
	 * @return
	 * @throws Exception
	 */
	private JSONObject getUserInfo(String token) throws Exception {
		String get_userInfo_url = PropertiesUtil.getValue("dyw.get_token_info");
		String get_user_info_url=get_userInfo_url+"?access_token="+token;
		String userInfoObject = restTemplate.getForObject(get_user_info_url,String.class);
		JSONObject dywUserInfoObject = new JSONObject(userInfoObject);
		logger.info("dyw."+dywUserInfoObject.toString());
		return dywUserInfoObject;
	}
}

            5.3登录策略:

@Component("loginServiceContext")
public class LoginServiceContext {
	
	@Autowired
	private Map<String,LoginService> loginSerivceMap = new HashMap<String,LoginService>();
	
	/**
	 * 重定向地址
	 * @param type
	 * @return
	 * @throws Exception
	 */
	public String login(String type) throws Exception {
		return loginSerivceMap.get(type).login();
	}
	/**
	 * 回调地址
	 * @param type
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	public String callback(String code,String type,HttpServletRequest request,HttpServletResponse response) throws Exception {
		return loginSerivceMap.get(type).callback(code,request,response);
	}
}

          5.4controller

@RequestMapping("login")
@Controller
public class LoginController {
	
	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired 
	private LoginServiceContext loginServiceContext;
	
	@RequestMapping("login")
	public String login(String type) throws Exception {
		String redirectUrl = loginServiceContext.login(type);
		logger.info(redirectUrl);
		return "redirect:"+redirectUrl;
	}
	@RequestMapping("callback")
	public String callback(HttpServletRequest request,HttpServletResponse response,String code,String type) throws Exception {
		String callback = loginServiceContext.callback(code,type, request,response);
		return "redirect:"+callback;
	}
	
}

        5.5对外提供第三方登录       

<html>
<head>
	<link rel="shortcut icon"type="image/x-icon" href="../imags/logo1.png" media="screen" />
	<style type="text/css">
		#search-button{
			width: 50px;
			text-align: center;
		}
		#search-button{
				opacity:0.9;
				border:1px solid #2d78f4;
				background-color:#3385ff;
		}
		#search-button:hover{
			opacity:1.0;
			background-color:#317ef3;
			border:1px solid #2868c8;
		}
		.btn-primary {
		    color: #3385ff;
		    text-decoration: none;
		}
		.btn-primary:hover{
		 	 color: #2d78f4;
		 	 text-decoration: underline;
		}
	</style>
	<script type="text/javascript" src="../jQuery/jquery-3.2.1.js"></script>
	<script src="../jQuery/jQuery.md5.js"></script>
	<script type="text/javascript">		
		 /* 根据参数名获取参数值*/
		 function getQueryString(name){
		     var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
		     var r = window.location.search.substr(1).match(reg);
		     if(r!=null)return  unescape(r[2]); return null;
		}
		 $(function(){
			 load();
		 })
		 function load(){
			 var client_id = getQueryString("client_id");
			 $.ajax({
			        type:'post',
			        dataType: "json",
			        url:"../application/getApplicationName.do",
			        data:{
			        	client_id:client_id,
			        	time:new Date()
			        },
			        success:function(data){
			        	var flag = data.success;
			        	if(flag){
			        		$("#application").text(data.data.info);
			        	}else{
			        	}
			        },
			        error:function(){
			        }
			    });
		 }
		 function login(){
			 var redirect_uri = getQueryString("redirect_uri");
			 var username = $("#username").val();
			 var password = $("#password").val();
			 $.ajax({
			        type:'post',
			        dataType: "json",
			        url:"../oauth2/login.do",
			        data:{
			        	redirect_uri:redirect_uri,
			        	username:username,
			        	password:$.md5(password),
			        	time:new Date()
			        },
			        success:function(data){
			        	var flag = data.success;
			        	if(flag){
			        		window.location.replace(data.data.info);
			        	}else{
			        		$("#msg").html("<font color='red'>"+data.data.msg+"</font>")
			        	}
			        },
			        error:function(){
			        }
			    });
		 }
	</script>
	
</head>
<body>
	
	<h1>对外提供第三方登录接口本地测试,其中一个账号:reyco,密码:123456。</h1>
	<div>
		<input id="redirect_uri" type="hidden" name="redirect_uri"><span id=msg></span></br>
		<input id="username" type="text" name="username"></br>
		<input id="password" type="text" name="password"></br>
		<input type="button" value="login" onclick="login()">
	</div>
	
	
	<div align="left">
		<div>
			<p class=""></p>
			<p class=""></p>
			<p class="">
				<a id="application" class="btn-primary" href="http://www.test.com" target="_blank"></a>
				将获得以下权限
			</p>
			<div class="" id="">
				<ul>
					<li>
						<input type="checkbox" id="select_all" hidefocus="true" checked="checked"/>
						<label for="select_all">全选</label>
					</li>
					<li>
						<input type="checkbox" hidefocus="true" id="item_80901010" title="默认授权 不可更改" hidefocus="true" checked disabled/>
						<label for="item_80901010" class="oauth_item_title">获得您的昵称、头像、性别</label>
					</li>
				</ul>
			</div>
			<div>
				<p>
					授权后表明你已同意 
					<a href="" class="btn-primary" target="_blank">dyw登录服务协议</a>
				</p>
			</div>		
			<div>
				<p>	
					<a href="http://www.test.com/manage.html" class="btn-primary" target="_blank">dyw登录</a>
					<span>|</span>
					<a href="http://www.test.com/manage.html" class="btn-primary" target="_blank">授权管理</a>
					<span>|</span>
					<a href="http://www.test.com/manage.html" class="btn-primary" target="_blank">申请接入</a>
				</p>
			</div>		
		</div>
	</div>	
</body>
</html>

         5.7调用第三方登录按照:

	<div><a href="../login/login.do?type=dyw" style="float: right;border-right: 100px" class="btn btn-link text-muted"><img src="../imags/dl.png"/></a></div>
	<div><a href="../login/login.do?type=qq" style="float: right;border-right: 100px" class="btn btn-link text-muted"><img src="../imags/qq.png"/></a></div>
	<div><a href="../login/login.do?type=baidu" style="float: right;border-right: 100px" class="btn btn-link text-muted"><img src="../imags/wx.png"/></a></div>
	<div><a href="../login/login.do?type=weibo" style="float: right;border-right: 100px" class="btn btn-link text-muted"><img src="../imags/wb.png"/></a></div>

如果有疑问可以看看我的另外一篇文章:对接第三方登录

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

java的艺术

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值