parent
43df2b3f8b
commit
e03a71776a
19 changed files with 517 additions and 23 deletions
@ -0,0 +1,31 @@ |
|||||||
|
package com.kob.backend.controller.user.account.acwing; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
import com.kob.backend.service.user.account.acwing.AcappService; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||||
|
import org.springframework.web.bind.annotation.RestController; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
@RestController |
||||||
|
public class AcappController { |
||||||
|
@Autowired |
||||||
|
private AcappService acappService; |
||||||
|
|
||||||
|
@GetMapping("/api/user/account/acwing/acapp/apply_code/") |
||||||
|
public JSONObject applyCode() { |
||||||
|
return acappService.applyCode(); |
||||||
|
} |
||||||
|
|
||||||
|
@GetMapping("/api/user/account/acwing/acapp/receive_code/") |
||||||
|
public JSONObject receiveCode(@RequestParam Map<String,String> data) { |
||||||
|
String code = data.get("code"); |
||||||
|
String state = data.get("state"); |
||||||
|
return acappService.receiveCode(code,state); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
||||||
|
|
@ -0,0 +1,27 @@ |
|||||||
|
package com.kob.backend.controller.user.account.acwing; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
import com.kob.backend.service.user.account.acwing.WebService; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||||
|
import org.springframework.web.bind.annotation.RequestParam; |
||||||
|
import org.springframework.web.bind.annotation.RestController; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
@RestController |
||||||
|
public class WebController { |
||||||
|
@Autowired |
||||||
|
private WebService webService; |
||||||
|
|
||||||
|
@GetMapping("/api/user/account/acwing/web/apply_code/") |
||||||
|
public JSONObject applyCode() { |
||||||
|
return webService.applyCode(); |
||||||
|
} |
||||||
|
@GetMapping("/api/user/account/acwing/web/receive_code/") |
||||||
|
public JSONObject receiveCode(@RequestParam Map<String,String> data) { |
||||||
|
String code = data.get("code"); |
||||||
|
String state = data.get("state"); |
||||||
|
return webService.receiveCode(code,state); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,136 @@ |
|||||||
|
package com.kob.backend.service.impl.user.account.acwing; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON; |
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
||||||
|
import com.kob.backend.mapper.UserMapper; |
||||||
|
import com.kob.backend.pojo.User; |
||||||
|
import com.kob.backend.service.impl.user.account.acwing.utils.HttpClientUtil; |
||||||
|
import com.kob.backend.service.user.account.acwing.AcappService; |
||||||
|
import com.kob.backend.utils.JwtUtil; |
||||||
|
import org.apache.http.NameValuePair; |
||||||
|
import org.apache.http.message.BasicNameValuePair; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.data.redis.core.RedisTemplate; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException; |
||||||
|
import java.net.URLEncoder; |
||||||
|
import java.time.Duration; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Random; |
||||||
|
|
||||||
|
@Service |
||||||
|
public class AcappServiceImpl implements AcappService { |
||||||
|
private static final String appId = "3357"; |
||||||
|
private static final String appSecret = "f343ff7eeaa649d2a257bffac0a9323a"; |
||||||
|
private static final String redirectUri = "https://kob.bnblogs.cc/api/user/account/acwing/acapp/receive_code/"; |
||||||
|
private static final String applyAccessTokenUrl = "https://www.acwing.com/third_party/api/oauth2/access_token/"; |
||||||
|
private static final String getUserInfoUrl = "https://www.acwing.com/third_party/api/meta/identity/getinfo/"; |
||||||
|
private static final Random random = new Random(); |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private UserMapper userMapper; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private RedisTemplate<String,String> redisTemplate; |
||||||
|
@Override |
||||||
|
public JSONObject applyCode() { |
||||||
|
JSONObject resp = new JSONObject(); |
||||||
|
resp.put("appid",appId); |
||||||
|
try { |
||||||
|
resp.put("redirect_uri", URLEncoder.encode(redirectUri,"UTF-8")); |
||||||
|
} catch (UnsupportedEncodingException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
resp.put("result","failed"); |
||||||
|
return resp; |
||||||
|
} |
||||||
|
|
||||||
|
resp.put("scope","userinfo"); |
||||||
|
|
||||||
|
StringBuilder state = new StringBuilder(); |
||||||
|
for (int i = 0; i < 10; i++) { |
||||||
|
state.append((char)(random.nextInt(10) + '0')); // 十位随机数字字符串
|
||||||
|
} |
||||||
|
resp.put("state",state.toString()); |
||||||
|
resp.put("result","success"); |
||||||
|
redisTemplate.opsForValue().set(state.toString(),"true"); // 将state值存入redis
|
||||||
|
redisTemplate.expire(state.toString(), Duration.ofMinutes(10)); // 设置过期时间为10分钟
|
||||||
|
return resp; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public JSONObject receiveCode(String code, String state) { |
||||||
|
JSONObject resp = new JSONObject(); |
||||||
|
resp.put("result","failed"); |
||||||
|
if (code == null || state == null) return resp; // 传入的code和state为空
|
||||||
|
if (Boolean.FALSE.equals(redisTemplate.hasKey(state))) return resp; // redis中没有该state
|
||||||
|
redisTemplate.delete(state); // 删除该state,只使用一次
|
||||||
|
|
||||||
|
// 获取accessToken
|
||||||
|
List<NameValuePair> nameValuePairs = new LinkedList<>(); |
||||||
|
nameValuePairs.add(new BasicNameValuePair("appid",appId)); |
||||||
|
nameValuePairs.add(new BasicNameValuePair("secret",appSecret)); |
||||||
|
nameValuePairs.add(new BasicNameValuePair("code",code)); |
||||||
|
|
||||||
|
String getString = HttpClientUtil.get(applyAccessTokenUrl,nameValuePairs); // 请求结果存入一个字符串
|
||||||
|
|
||||||
|
if (getString == null) return resp; |
||||||
|
|
||||||
|
JSONObject getResp = JSONObject.parseObject(getString); |
||||||
|
String accessToken = getResp.getString("access_token"); |
||||||
|
String openId = getResp.getString("openid"); |
||||||
|
|
||||||
|
if (accessToken == null || openId == null) return resp; |
||||||
|
|
||||||
|
QueryWrapper<User> qw = new QueryWrapper<>(); |
||||||
|
qw.eq("openid",openId); |
||||||
|
List<User> users = userMapper.selectList(qw); // 查询满足openid的用户是否存在
|
||||||
|
if (!users.isEmpty()) { |
||||||
|
User user = users.get(0); |
||||||
|
String jwt = JwtUtil.createJWT(user.getId().toString()); |
||||||
|
resp.put("result","success"); |
||||||
|
resp.put("jwt_token",jwt); |
||||||
|
return resp; |
||||||
|
} |
||||||
|
|
||||||
|
// 如果不存在说明该用户没有登录过,需要根据上面的accessToken和openid向Acwing请求用户信息
|
||||||
|
|
||||||
|
nameValuePairs = new LinkedList<>(); |
||||||
|
nameValuePairs.add(new BasicNameValuePair("access_token",accessToken)); |
||||||
|
nameValuePairs.add(new BasicNameValuePair("openid",openId)); |
||||||
|
|
||||||
|
getString = HttpClientUtil.get(getUserInfoUrl,nameValuePairs); // 将请求结果存入字符串
|
||||||
|
|
||||||
|
if (getString == null) return resp; |
||||||
|
getResp = JSONObject.parseObject(getString); |
||||||
|
// 获得用户的用户名和头像
|
||||||
|
String username = getResp.getString("username"); |
||||||
|
String photo = getResp.getString("photo"); |
||||||
|
|
||||||
|
if (username == null || photo == null) return resp; |
||||||
|
|
||||||
|
// 避免新出现的用户重名
|
||||||
|
for (int i = 0; i < 100; i++) { // 随机在后面添加以为数字
|
||||||
|
QueryWrapper<User> queryWrapper = new QueryWrapper<>(); |
||||||
|
queryWrapper.eq("username",username); |
||||||
|
// 没有重名,直接退出
|
||||||
|
if (userMapper.selectList(queryWrapper).isEmpty()) break; |
||||||
|
username += (char)(random.nextInt(10) + '0'); |
||||||
|
if (i == 99) return resp; // 小概率事件,太逆天,直接返回
|
||||||
|
} |
||||||
|
|
||||||
|
// 根据获得的信息建立一个用户
|
||||||
|
User user = new User(null,username,null,photo,null,openId); |
||||||
|
userMapper.insert(user); |
||||||
|
|
||||||
|
String jwt = JwtUtil.createJWT(user.getId().toString()); |
||||||
|
|
||||||
|
resp.put("result","success"); |
||||||
|
resp.put("jwt_token",jwt); |
||||||
|
|
||||||
|
return resp; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,138 @@ |
|||||||
|
package com.kob.backend.service.impl.user.account.acwing; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
||||||
|
import com.kob.backend.mapper.UserMapper; |
||||||
|
import com.kob.backend.pojo.User; |
||||||
|
import com.kob.backend.service.impl.user.account.acwing.utils.HttpClientUtil; |
||||||
|
import com.kob.backend.service.user.account.acwing.WebService; |
||||||
|
import com.kob.backend.utils.JwtUtil; |
||||||
|
import org.apache.http.NameValuePair; |
||||||
|
import org.apache.http.message.BasicNameValuePair; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.data.redis.core.RedisTemplate; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException; |
||||||
|
import java.net.URLEncoder; |
||||||
|
import java.time.Duration; |
||||||
|
import java.util.LinkedList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.Random; |
||||||
|
|
||||||
|
@Service |
||||||
|
public class WebServiceImpl implements WebService { |
||||||
|
private static final String appId = "3357"; |
||||||
|
private static final String appSecret = "f343ff7eeaa649d2a257bffac0a9323a"; |
||||||
|
private static final String redirectUri = "https://kob.bnblogs.cc/user/account/acwing/web/receive_code/"; |
||||||
|
private static final String applyAccessTokenUrl = "https://www.acwing.com/third_party/api/oauth2/access_token/"; |
||||||
|
private static final String getUserInfoUrl = "https://www.acwing.com/third_party/api/meta/identity/getinfo/"; |
||||||
|
private static final Random random = new Random(); |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private UserMapper userMapper; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private RedisTemplate<String,String> redisTemplate; |
||||||
|
|
||||||
|
@Override |
||||||
|
public JSONObject applyCode() { |
||||||
|
JSONObject resp = new JSONObject(); |
||||||
|
String encodeUrl=""; |
||||||
|
try { |
||||||
|
encodeUrl = URLEncoder.encode(redirectUri,"UTF-8"); |
||||||
|
} catch (UnsupportedEncodingException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
resp.put("result","failed"); |
||||||
|
return resp; |
||||||
|
} |
||||||
|
|
||||||
|
StringBuilder state = new StringBuilder(); |
||||||
|
for (int i = 0; i < 10; i++) { |
||||||
|
state.append((char)(random.nextInt(10) + '0')); // 十位随机数字字符串
|
||||||
|
} |
||||||
|
resp.put("result","success"); |
||||||
|
redisTemplate.opsForValue().set(state.toString(),"true"); // 将state值存入redis
|
||||||
|
redisTemplate.expire(state.toString(), Duration.ofMinutes(10)); // 设置过期时间为10分钟
|
||||||
|
|
||||||
|
String applyCodeUrl = "https://www.acwing.com/third_party/api/oauth2/web/authorize/?appid=" + appId |
||||||
|
+ "&redirect_uri=" + encodeUrl |
||||||
|
+ "&scope=userinfo" |
||||||
|
+ "&state=" + state; |
||||||
|
resp.put("apply_code_url",applyCodeUrl); |
||||||
|
return resp; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public JSONObject receiveCode(String code, String state) { |
||||||
|
JSONObject resp = new JSONObject(); |
||||||
|
resp.put("result","failed"); |
||||||
|
if (code == null || state == null) return resp; // 传入的code和state为空
|
||||||
|
if (Boolean.FALSE.equals(redisTemplate.hasKey(state))) return resp; // redis中没有该state
|
||||||
|
redisTemplate.delete(state); // 删除该state,只使用一次
|
||||||
|
|
||||||
|
// 获取accessToken
|
||||||
|
List<NameValuePair> nameValuePairs = new LinkedList<>(); |
||||||
|
nameValuePairs.add(new BasicNameValuePair("appid",appId)); |
||||||
|
nameValuePairs.add(new BasicNameValuePair("secret",appSecret)); |
||||||
|
nameValuePairs.add(new BasicNameValuePair("code",code)); |
||||||
|
|
||||||
|
String getString = HttpClientUtil.get(applyAccessTokenUrl,nameValuePairs); // 请求结果存入一个字符串
|
||||||
|
|
||||||
|
if (getString == null) return resp; |
||||||
|
|
||||||
|
JSONObject getResp = JSONObject.parseObject(getString); |
||||||
|
String accessToken = getResp.getString("access_token"); |
||||||
|
String openId = getResp.getString("openid"); |
||||||
|
|
||||||
|
if (accessToken == null || openId == null) return resp; |
||||||
|
|
||||||
|
QueryWrapper<User> qw = new QueryWrapper<>(); |
||||||
|
qw.eq("openid",openId); |
||||||
|
List<User> users = userMapper.selectList(qw); // 查询满足openid的用户是否存在
|
||||||
|
if (!users.isEmpty()) { |
||||||
|
User user = users.get(0); |
||||||
|
String jwt = JwtUtil.createJWT(user.getId().toString()); |
||||||
|
resp.put("result","success"); |
||||||
|
resp.put("jwt_token",jwt); |
||||||
|
return resp; |
||||||
|
} |
||||||
|
|
||||||
|
// 如果不存在说明该用户没有登录过,需要根据上面的accessToken和openid向Acwing请求用户信息
|
||||||
|
|
||||||
|
nameValuePairs = new LinkedList<>(); |
||||||
|
nameValuePairs.add(new BasicNameValuePair("access_token",accessToken)); |
||||||
|
nameValuePairs.add(new BasicNameValuePair("openid",openId)); |
||||||
|
|
||||||
|
getString = HttpClientUtil.get(getUserInfoUrl,nameValuePairs); // 将请求结果存入字符串
|
||||||
|
|
||||||
|
if (getString == null) return resp; |
||||||
|
getResp = JSONObject.parseObject(getString); |
||||||
|
// 获得用户的用户名和头像
|
||||||
|
String username = getResp.getString("username"); |
||||||
|
String photo = getResp.getString("photo"); |
||||||
|
|
||||||
|
if (username == null || photo == null) return resp; |
||||||
|
|
||||||
|
// 避免新出现的用户重名
|
||||||
|
for (int i = 0; i < 100; i++) { // 随机在后面添加以为数字
|
||||||
|
QueryWrapper<User> queryWrapper = new QueryWrapper<>(); |
||||||
|
queryWrapper.eq("username",username); |
||||||
|
// 没有重名,直接退出
|
||||||
|
if (userMapper.selectList(queryWrapper).isEmpty()) break; |
||||||
|
username += (char)(random.nextInt(10) + '0'); |
||||||
|
if (i == 99) return resp; // 小概率事件,太逆天,直接返回
|
||||||
|
} |
||||||
|
|
||||||
|
// 根据获得的信息建立一个用户
|
||||||
|
User user = new User(null,username,null,photo,null,openId); |
||||||
|
userMapper.insert(user); |
||||||
|
|
||||||
|
String jwt = JwtUtil.createJWT(user.getId().toString()); |
||||||
|
|
||||||
|
resp.put("result","success"); |
||||||
|
resp.put("jwt_token",jwt); |
||||||
|
|
||||||
|
return resp; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
package com.kob.backend.service.impl.user.account.acwing.utils; |
||||||
|
|
||||||
|
|
||||||
|
import org.apache.http.HttpEntity; |
||||||
|
import org.apache.http.NameValuePair; |
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse; |
||||||
|
import org.apache.http.client.methods.HttpGet; |
||||||
|
import org.apache.http.client.utils.URIBuilder; |
||||||
|
import org.apache.http.impl.client.CloseableHttpClient; |
||||||
|
import org.apache.http.impl.client.HttpClients; |
||||||
|
import org.apache.http.util.EntityUtils; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.net.URISyntaxException; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
public class HttpClientUtil { |
||||||
|
public static String get(String url, List<NameValuePair> params) { |
||||||
|
URIBuilder uriBuilder = null; |
||||||
|
try { |
||||||
|
uriBuilder = new URIBuilder(url); |
||||||
|
} catch (URISyntaxException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
return null; |
||||||
|
} |
||||||
|
uriBuilder.setParameters(params); |
||||||
|
|
||||||
|
try (CloseableHttpClient client = HttpClients.createDefault()) { |
||||||
|
HttpGet httpGet = new HttpGet(uriBuilder.build()); |
||||||
|
CloseableHttpResponse response = client.execute(httpGet); |
||||||
|
HttpEntity entity = response.getEntity(); |
||||||
|
return EntityUtils.toString(entity); |
||||||
|
} catch (IOException | URISyntaxException e) { |
||||||
|
e.printStackTrace(); |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
package com.kob.backend.service.user.account.acwing; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
|
||||||
|
public interface AcappService { |
||||||
|
JSONObject applyCode(); |
||||||
|
JSONObject receiveCode(String code,String state); |
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
package com.kob.backend.service.user.account.acwing; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject; |
||||||
|
|
||||||
|
public interface WebService { |
||||||
|
JSONObject applyCode(); |
||||||
|
JSONObject receiveCode(String code,String state); |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
<template> |
||||||
|
<div></div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import $ from 'jquery'; |
||||||
|
import router from '@/router/index' |
||||||
|
import { useRoute } from "vue-router" |
||||||
|
import { useStore } from "vuex"; |
||||||
|
|
||||||
|
export default { |
||||||
|
setup() { |
||||||
|
const myRouter = useRoute(); |
||||||
|
const store= useStore(); |
||||||
|
$.ajax({ |
||||||
|
url: "https://kob.bnblogs.cc/api/user/account/acwing/web/receive_code/", |
||||||
|
type: "GET", |
||||||
|
data: { |
||||||
|
code: myRouter.query.code, |
||||||
|
state: myRouter.query.state, |
||||||
|
}, |
||||||
|
success: resp => { |
||||||
|
if (resp.result === "success") { |
||||||
|
console.log(resp); |
||||||
|
// 保存jwt_token |
||||||
|
localStorage.setItem("jwt_token",resp.jwt_token); |
||||||
|
store.commit("updateToken",resp.jwt_token); |
||||||
|
router.push({ name:"home" }); // 验证成功跳转到首页 |
||||||
|
store.commit("updatePullingInfo",false); |
||||||
|
}else { // 用户拒绝授权,跳转到注册页面 |
||||||
|
router.push({ name:"register" }); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
|
||||||
|
<style scoped> |
||||||
|
|
||||||
|
</style> |
Loading…
Reference in new issue