模拟第三方登录开放接口

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

    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 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 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 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 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 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 loginSerivceMap = new HashMap();
	
	/**
	 * 重定向地址
	 * @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对外提供第三方登录       



	
	
	
	
	
	


	
	

对外提供第三方登录接口本地测试,其中一个账号:reyco,密码:123456。




将获得以下权限

授权后表明你已同意 dyw登录服务协议

         5.7调用第三方登录按照:

	

 

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

 

 

 

 

你可能感兴趣的:(模拟第三方登录开放接口)