|
@@ -1,17 +1,22 @@
|
|
|
package com.yonge.cooleshow.auth.web.controller;
|
|
|
|
|
|
-import io.swagger.annotations.Api;
|
|
|
-import io.swagger.annotations.ApiImplicitParam;
|
|
|
-import io.swagger.annotations.ApiImplicitParams;
|
|
|
-import io.swagger.annotations.ApiOperation;
|
|
|
+import com.yonge.cooleshow.auth.api.dto.QRLoginDto;
|
|
|
+import com.yonge.cooleshow.common.enums.CacheNameEnum;
|
|
|
+import com.yonge.cooleshow.common.util.TokenUtil;
|
|
|
+import com.yonge.toolset.base.util.StringUtil;
|
|
|
+import io.swagger.annotations.*;
|
|
|
|
|
|
import java.io.IOException;
|
|
|
import java.util.Base64;
|
|
|
+import java.util.Calendar;
|
|
|
import java.util.Map;
|
|
|
+import java.util.UUID;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.redisson.api.RedissonClient;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.http.HttpEntity;
|
|
|
import org.springframework.http.HttpHeaders;
|
|
@@ -24,10 +29,7 @@ import org.springframework.security.oauth2.provider.token.ResourceServerTokenSer
|
|
|
import org.springframework.security.oauth2.provider.token.TokenStore;
|
|
|
import org.springframework.util.LinkedMultiValueMap;
|
|
|
import org.springframework.util.MultiValueMap;
|
|
|
-import org.springframework.web.bind.annotation.GetMapping;
|
|
|
-import org.springframework.web.bind.annotation.PathVariable;
|
|
|
-import org.springframework.web.bind.annotation.PostMapping;
|
|
|
-import org.springframework.web.bind.annotation.RestController;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
import org.springframework.web.client.RestTemplate;
|
|
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
@@ -43,130 +45,240 @@ import com.yonge.cooleshow.common.security.SecurityUtils;
|
|
|
@Api(tags = "认证服务")
|
|
|
public class TokenController extends BaseController {
|
|
|
|
|
|
- @Autowired
|
|
|
- private CustomTokenServices tokenService;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private ResourceServerTokenServices resourceServerTokenServices;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private TokenStore tokenStore;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private RestTemplate restTemplate;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private ObjectMapper objectMapper;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private SysUserService userService;
|
|
|
-
|
|
|
- @PostMapping(value = "/smsLogin",consumes = MediaType.APPLICATION_JSON_VALUE)
|
|
|
- @ApiOperation(value = "短信验证码的方式登录")
|
|
|
- @ApiImplicitParams({ @ApiImplicitParam(name = "smsCode", value = "验证码", required = true, dataType = "String"),
|
|
|
- @ApiImplicitParam(name = "clientSecret", value = "固定传 app", required = true, dataType = "String"),
|
|
|
- @ApiImplicitParam(name = "clientId", value = "固定传 app", required = true, dataType = "String"),
|
|
|
- @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String") })
|
|
|
+ @Autowired
|
|
|
+ private CustomTokenServices tokenService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ResourceServerTokenServices resourceServerTokenServices;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private TokenStore tokenStore;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RestTemplate restTemplate;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ObjectMapper objectMapper;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private SysUserService userService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private RedissonClient redissonClient;
|
|
|
+
|
|
|
+ @PostMapping(value = "/smsLogin", consumes = MediaType.APPLICATION_JSON_VALUE)
|
|
|
+ @ApiOperation(value = "短信验证码的方式登录")
|
|
|
+ @ApiImplicitParams({@ApiImplicitParam(name = "smsCode", value = "验证码", required = true, dataType = "String"),
|
|
|
+ @ApiImplicitParam(name = "clientSecret", value = "固定传 app", required = true, dataType = "String"),
|
|
|
+ @ApiImplicitParam(name = "clientId", value = "固定传 app", required = true, dataType = "String"),
|
|
|
+ @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "String")})
|
|
|
public Object smsLogin() {
|
|
|
- return succeed();
|
|
|
+ return succeed();
|
|
|
}
|
|
|
|
|
|
@GetMapping("/queryUserInfo")
|
|
|
public SysUser queryUserInfo() {
|
|
|
- AuthUser authUser = SecurityUtils.getUser();
|
|
|
- if(authUser != null){
|
|
|
- return userService.get(authUser.getUserId());
|
|
|
- }
|
|
|
- return null;
|
|
|
+ AuthUser authUser = SecurityUtils.getUser();
|
|
|
+ if (authUser != null) {
|
|
|
+ return userService.get(authUser.getUserId());
|
|
|
+ }
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
- @ApiOperation(value = "获取用户信息")
|
|
|
+ @ApiOperation(value = "获取用户信息")
|
|
|
@GetMapping("/api/queryUserInfo")
|
|
|
public Object apiQueryUserInfo() {
|
|
|
- AuthUser authUser = SecurityUtils.getUser();
|
|
|
- if(authUser != null){
|
|
|
- return succeed(userService.queryUserInfo(authUser.getUserId()));
|
|
|
- }
|
|
|
- return failed("获取用户信息失败");
|
|
|
+ AuthUser authUser = SecurityUtils.getUser();
|
|
|
+ if (authUser != null) {
|
|
|
+ return succeed(userService.queryUserInfo(authUser.getUserId()));
|
|
|
+ }
|
|
|
+ return failed("获取用户信息失败");
|
|
|
}
|
|
|
-
|
|
|
- @PostMapping(value = "/usernameLogin",consumes = MediaType.APPLICATION_JSON_VALUE)
|
|
|
- @ApiOperation(value = "手机号密码方式登录")
|
|
|
- @ApiImplicitParams({ @ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "String"),
|
|
|
- @ApiImplicitParam(name = "clientSecret", value = "固定传 app", required = true, dataType = "String"),
|
|
|
- @ApiImplicitParam(name = "clientId", value = "固定传 app", required = true, dataType = "String"),
|
|
|
- @ApiImplicitParam(name = "username", value = "手机号", required = true, dataType = "String") })
|
|
|
+
|
|
|
+ @PostMapping(value = "/usernameLogin", consumes = MediaType.APPLICATION_JSON_VALUE)
|
|
|
+ @ApiOperation(value = "手机号密码方式登录")
|
|
|
+ @ApiImplicitParams({@ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "String"),
|
|
|
+ @ApiImplicitParam(name = "clientSecret", value = "固定传 app", required = true, dataType = "String"),
|
|
|
+ @ApiImplicitParam(name = "clientId", value = "固定传 app", required = true, dataType = "String"),
|
|
|
+ @ApiImplicitParam(name = "username", value = "手机号", required = true, dataType = "String")})
|
|
|
public Object usernameLogin() {
|
|
|
- return succeed();
|
|
|
+ return succeed();
|
|
|
}
|
|
|
|
|
|
- @PostMapping(value = "/refreshToken",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
|
|
- @ApiOperation(value = "刷新token")
|
|
|
- public HttpResponseResult refreshToken(String refreshToken, String clientId, String clientSecret) throws IOException {
|
|
|
- String url = "http://auth-server/oauth/token";
|
|
|
+ @PostMapping(value = "/refreshToken", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
|
|
+ @ApiOperation(value = "刷新token")
|
|
|
+ public HttpResponseResult refreshToken(String refreshToken, String clientId, String clientSecret) throws IOException {
|
|
|
+ String url = "http://auth-server/oauth/token";
|
|
|
+
|
|
|
+ String base64ClientCredentials = Base64.getEncoder().encodeToString((clientId + ":" + clientSecret).getBytes());
|
|
|
|
|
|
- String base64ClientCredentials = Base64.getEncoder().encodeToString((clientId + ":" + clientSecret).getBytes());
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.add("Authorization", "Basic " + base64ClientCredentials);
|
|
|
+ headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
|
|
|
|
|
- HttpHeaders headers = new HttpHeaders();
|
|
|
- headers.add("Authorization", "Basic " + base64ClientCredentials);
|
|
|
- headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
|
|
+ MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
|
|
|
+ params.add("refresh_token", refreshToken);
|
|
|
+ params.add("grant_type", "refresh_token");
|
|
|
+ params.add("client_id", clientId);
|
|
|
+ params.add("client_secret", clientSecret);
|
|
|
|
|
|
- MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
|
|
|
- params.add("refresh_token", refreshToken);
|
|
|
- params.add("grant_type", "refresh_token");
|
|
|
- params.add("client_id", clientId);
|
|
|
- params.add("client_secret", clientSecret);
|
|
|
+ HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<MultiValueMap<String, String>>(params, headers);
|
|
|
|
|
|
- HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<MultiValueMap<String, String>>(params, headers);
|
|
|
+ ResponseEntity<String> resp = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
|
|
|
|
|
|
- ResponseEntity<String> resp = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
|
|
|
+ return succeed(objectMapper.readValue(resp.getBody(), Map.class));
|
|
|
+ }
|
|
|
|
|
|
- return succeed(objectMapper.readValue(resp.getBody(), Map.class));
|
|
|
- }
|
|
|
+ @GetMapping(value = "exit")
|
|
|
+ @ApiOperation(value = "退出登录")
|
|
|
+ public HttpResponseResult<String> logout(HttpServletRequest request) {
|
|
|
+ String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
|
|
|
+ if (StringUtils.isBlank(authHeader)) {
|
|
|
+ return failed("退出失败,token 为空");
|
|
|
+ }
|
|
|
|
|
|
- @GetMapping(value = "exit")
|
|
|
- @ApiOperation(value = "退出登录")
|
|
|
- public HttpResponseResult<String> logout(HttpServletRequest request) {
|
|
|
- String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
|
|
|
- if (StringUtils.isBlank(authHeader)) {
|
|
|
- return failed("退出失败,token 为空");
|
|
|
- }
|
|
|
+ String tokenValue = authHeader.toLowerCase().replace(OAuth2AccessToken.BEARER_TYPE.toLowerCase(), StringUtils.EMPTY).trim();
|
|
|
|
|
|
- String tokenValue = authHeader.toLowerCase().replace(OAuth2AccessToken.BEARER_TYPE.toLowerCase(), StringUtils.EMPTY).trim();
|
|
|
+ tokenService.revokeToken(tokenValue);
|
|
|
|
|
|
- tokenService.revokeToken(tokenValue);
|
|
|
+ return succeed("退出成功");
|
|
|
+ }
|
|
|
|
|
|
- return succeed("退出成功");
|
|
|
- }
|
|
|
+ @PostMapping(value = "exit/{clientId}/{phone}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
|
|
+ @ApiOperation(value = "指定用户退出登录")
|
|
|
+ public HttpResponseResult<String> exitByPhone(@PathVariable("clientId") String clientId, @PathVariable("phone") String phone) {
|
|
|
|
|
|
- @PostMapping(value = "exit/{clientId}/{phone}", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
|
|
- @ApiOperation(value = "指定用户退出登录")
|
|
|
- public HttpResponseResult<String> exitByPhone(@PathVariable("clientId") String clientId, @PathVariable("phone") String phone) {
|
|
|
+ return tokenService.revokeToken(clientId, phone) ? succeed("退出成功") : failed();
|
|
|
+ }
|
|
|
|
|
|
- return tokenService.revokeToken(clientId, phone) ? succeed("退出成功") : failed();
|
|
|
- }
|
|
|
+ @GetMapping(value = "/checkToken", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
|
|
+ @ApiOperation(value = "检查token")
|
|
|
+ public HttpResponseResult<Object> checkToken(HttpServletRequest request) throws IOException {
|
|
|
|
|
|
- @GetMapping(value = "/checkToken",consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
|
|
- @ApiOperation(value = "检查token")
|
|
|
- public HttpResponseResult<Object> checkToken(HttpServletRequest request) throws IOException {
|
|
|
+ String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
|
|
|
+ if (StringUtils.isBlank(authHeader)) {
|
|
|
+ return failed(HttpStatus.FORBIDDEN, "token 为空");
|
|
|
+ }
|
|
|
|
|
|
- String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
|
|
|
- if (StringUtils.isBlank(authHeader)) {
|
|
|
- return failed(HttpStatus.FORBIDDEN, "token 为空");
|
|
|
- }
|
|
|
+ String tokenValue = authHeader.toLowerCase().replace(OAuth2AccessToken.BEARER_TYPE.toLowerCase(), StringUtils.EMPTY).trim();
|
|
|
|
|
|
- String tokenValue = authHeader.toLowerCase().replace(OAuth2AccessToken.BEARER_TYPE.toLowerCase(), StringUtils.EMPTY).trim();
|
|
|
+ OAuth2AccessToken accessToken = resourceServerTokenServices.readAccessToken(tokenValue);
|
|
|
+ if (accessToken == null) {
|
|
|
+ return failed(HttpStatus.FORBIDDEN, "token 无效");
|
|
|
+ }
|
|
|
|
|
|
- OAuth2AccessToken accessToken = resourceServerTokenServices.readAccessToken(tokenValue);
|
|
|
- if (accessToken == null) {
|
|
|
- return failed(HttpStatus.FORBIDDEN, "token 无效");
|
|
|
- }
|
|
|
+ if (accessToken.isExpired()) {
|
|
|
+ return failed(HttpStatus.FORBIDDEN, "token 已过期");
|
|
|
+ }
|
|
|
|
|
|
- if (accessToken.isExpired()) {
|
|
|
- return failed(HttpStatus.FORBIDDEN, "token 已过期");
|
|
|
- }
|
|
|
+ return succeed();
|
|
|
+ }
|
|
|
|
|
|
- return succeed();
|
|
|
- }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取二维码登录code(不需要鉴权)
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @GetMapping("/getQRLoginCode")
|
|
|
+ @ApiOperation(value = "获取二维码登录code")
|
|
|
+ public HttpResponseResult<QRLoginDto> getQRLoginCode(
|
|
|
+ @ApiParam(value = "clientId", required = true) @RequestParam("clientId") String clientId,
|
|
|
+ @ApiParam(value = "clientSecret", required = true) @RequestParam("clientSecret") String clientSecret) {
|
|
|
+ //todo 验证客户端id
|
|
|
+
|
|
|
+ QRLoginDto qrLogin = new QRLoginDto();
|
|
|
+
|
|
|
+ UUID uuid = UUID.randomUUID();
|
|
|
+ qrLogin.setCode(uuid.toString());
|
|
|
+
|
|
|
+ Calendar instance = Calendar.getInstance();
|
|
|
+ instance.add(Calendar.MINUTE, 5);
|
|
|
+ qrLogin.setExpireTime(instance.getTime());
|
|
|
+ qrLogin.setClientId(clientId);
|
|
|
+ qrLogin.setClientSecret(clientSecret);
|
|
|
+ qrLogin.setCodeStatus("no_scan");
|
|
|
+
|
|
|
+ redissonClient.getBucket(CacheNameEnum.QR_LOGIN_CODE.getRedisKey(uuid.toString()))
|
|
|
+ .set(qrLogin, 5, TimeUnit.MINUTES);
|
|
|
+
|
|
|
+ return HttpResponseResult.succeed(qrLogin);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 前端轮询登录(不需要鉴权)
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @GetMapping("/pollingQRLoginCode")
|
|
|
+ @ApiOperation(value = "获取二维码登录code")
|
|
|
+ public HttpResponseResult<QRLoginDto> pollingQRLoginCode(@ApiParam(value = "二维码登录code", required = true) @RequestParam("code") String code) {
|
|
|
+ if (StringUtil.isEmpty(code)) {
|
|
|
+ return HttpResponseResult.failed("登录失败");
|
|
|
+ }
|
|
|
+ Object data = redissonClient.getBucket(CacheNameEnum.QR_LOGIN_CODE.getRedisKey(code))
|
|
|
+ .get();
|
|
|
+ if (null != data) {
|
|
|
+ QRLoginDto dto = (QRLoginDto) data;
|
|
|
+ return HttpResponseResult.succeed(dto);
|
|
|
+ } else {
|
|
|
+ return HttpResponseResult.failed("二维码已过期");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 二维码登录
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ * @throws IOException
|
|
|
+ */
|
|
|
+ @GetMapping(value = "/qrLogin")
|
|
|
+ @ApiOperation(value = "二维码登录")
|
|
|
+ public HttpResponseResult<QRLoginDto> qrLogin(
|
|
|
+ @ApiParam(value = "二维码登录code", required = true) @RequestParam("code") String code
|
|
|
+ ) throws IOException {
|
|
|
+ Object data = redissonClient.getBucket(CacheNameEnum.QR_LOGIN_CODE.getRedisKey(code))
|
|
|
+ .get();
|
|
|
+ if (null == data) {
|
|
|
+ return HttpResponseResult.failed("二维码已过期");
|
|
|
+ }
|
|
|
+
|
|
|
+ AuthUser authUser = SecurityUtils.getUser();
|
|
|
+ if (authUser == null) {
|
|
|
+ return HttpResponseResult.failed("请先登录");
|
|
|
+ }
|
|
|
+ QRLoginDto dto = (QRLoginDto) data;
|
|
|
+ dto.setCodeStatus("scanned");
|
|
|
+ redissonClient.getBucket(CacheNameEnum.QR_LOGIN_CODE.getRedisKey(code)).set(dto,5,TimeUnit.MINUTES);
|
|
|
+
|
|
|
+ String url = "http://auth-server/oauth/token";
|
|
|
+
|
|
|
+ String userType = TokenUtil.getClientIdFromHeader();
|
|
|
+ String base64ClientCredentials = Base64.getEncoder().encodeToString((dto.getClientId() + ":" + dto.getClientSecret()).getBytes());
|
|
|
+
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
+ headers.add("Authorization", "Basic " + base64ClientCredentials);
|
|
|
+ headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
|
|
+
|
|
|
+ MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
|
|
|
+ params.add("client_id", dto.getClientId());
|
|
|
+ params.add("client_secret", dto.getClientSecret());
|
|
|
+ params.add("username", authUser.getUsername());
|
|
|
+ params.add("password", authUser.getPassword());
|
|
|
+ params.add("grant_type", "password");
|
|
|
+
|
|
|
+ HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<MultiValueMap<String, String>>(params, headers);
|
|
|
+
|
|
|
+ ResponseEntity<String> resp = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
|
|
|
+
|
|
|
+ Map map = objectMapper.readValue(resp.getBody(), Map.class);
|
|
|
+
|
|
|
+ dto.setUserType(userType);
|
|
|
+ dto.setCodeStatus("succeed");
|
|
|
+ dto.setToken(map);
|
|
|
+ redissonClient.getBucket(CacheNameEnum.QR_LOGIN_CODE.getRedisKey(code)).set(dto,5,TimeUnit.MINUTES);
|
|
|
+ return succeed(dto);
|
|
|
+ }
|
|
|
|
|
|
}
|