package com.kidgrow.oauth2.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.kidgrow.authclient.token.MobileAuthenticationToken;
import com.kidgrow.authclient.token.OpenIdAuthenticationToken;
import com.kidgrow.authclient.util.AuthUtils;
import com.kidgrow.common.constant.SecurityConstants;
import com.kidgrow.common.context.ClientContextHolder;
import com.kidgrow.common.utils.AesUtils;
import com.kidgrow.common.utils.ResponseUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.UnapprovedClientAuthenticationException;
import org.springframework.security.oauth2.provider.*;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 石家庄喜高科技有限责任公司 版权所有 © Copyright 2020
*
* @Description: Oauth2相关操作
* @Project:
* @CreateDate: Created in 2020/2/20 09:19
* @Author: liuke
*/
@Api(tags = "OAuth2相关操作")
@Slf4j
@RestController
public class OAuth2Controller {
@Resource
private ObjectMapper objectMapper;
@Autowired
private PasswordEncoder passwordEncoder;
@Resource
private AuthorizationServerTokenServices authorizationServerTokenServices;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private ClientDetailsService clientDetailsService;
@ApiOperation(value = "用户名密码获取token")
@PostMapping(SecurityConstants.PASSWORD_LOGIN_PRO_URL)
public void getUserTokenInfo(
@ApiParam(required = true, name = "username", value = "账号") String username,
@ApiParam(required = true, name = "password", value = "密码") String password,
HttpServletRequest request, HttpServletResponse response) throws Exception {
//先解密
String decryptName = AesUtils.desEncrypt(username).trim();
String decryptPwd = AesUtils.desEncrypt(password).trim();
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(decryptName, decryptPwd);
writerToken(request, response, token, "用户名或密码错误");
}
@ApiOperation(value = "openId获取token")
@PostMapping(SecurityConstants.OPENID_TOKEN_URL)
public void getTokenByOpenId(
@ApiParam(required = true, name = "openId", value = "openId") String openId,
HttpServletRequest request, HttpServletResponse response) throws IOException {
OpenIdAuthenticationToken token = new OpenIdAuthenticationToken(openId);
writerToken(request, response, token, "openId错误");
}
@ApiOperation(value = "mobile获取token")
@PostMapping(SecurityConstants.MOBILE_TOKEN_URL)
public void getTokenByMobile(
@ApiParam(required = true, name = "mobile", value = "mobile") String mobile,
@ApiParam(required = true, name = "password", value = "密码") String password,
HttpServletRequest request, HttpServletResponse response) throws IOException {
MobileAuthenticationToken token = new MobileAuthenticationToken(mobile, password);
writerToken(request, response, token, "手机号或密码错误");
}
private void writerToken(HttpServletRequest request, HttpServletResponse response, AbstractAuthenticationToken token
, String badCredenbtialsMsg) throws IOException {
try {
final String[] clientInfos = AuthUtils.extractClient(request);
String clientId = clientInfos[0];
String clientSecret = clientInfos[1];
ClientDetails clientDetails = getClient(clientId, clientSecret);
// String tenantId="";
// //保存租户id,租户id根据业务尽进行替换
// switch (clientId){
// case "hospital":
// tenantId="1";
// break;
// case "webApp":
// tenantId="webApp";
// break;
// }
//
// TenantContextHolder.setTenant(tenantId);
ClientContextHolder.setClient(clientId);
TokenRequest tokenRequest = new TokenRequest(MapUtils.EMPTY_SORTED_MAP, clientId, clientDetails.getScope(), "password");
OAuth2Request oAuth2Request = tokenRequest.createOAuth2Request(clientDetails);
Authentication authentication = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(oAuth2Request, authentication);
OAuth2AccessToken oAuth2AccessToken = authorizationServerTokenServices.createAccessToken(oAuth2Authentication);
oAuth2Authentication.setAuthenticated(true);
ResponseUtil.responseSucceed(objectMapper, response, oAuth2AccessToken);
} catch (BadCredentialsException | InternalAuthenticationServiceException e) {
exceptionHandler(response, badCredenbtialsMsg);
} catch (Exception e) {
exceptionHandler(response, e);
}
}
private void exceptionHandler(HttpServletResponse response, Exception e) throws IOException {
log.error("exceptionHandler-error:", e);
exceptionHandler(response, e.getMessage());
}
private void exceptionHandler(HttpServletResponse response, String msg) throws IOException {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
ResponseUtil.responseFailed(objectMapper, response, msg);
}
private ClientDetails getClient(String clientId, String clientSecret) {
ClientDetails clientDetails = clientDetailsService.loadClientByClientId(clientId);
if (clientDetails == null) {
throw new UnapprovedClientAuthenticationException("clientId对应的信息不存在");
} else if (!passwordEncoder.matches(clientSecret, clientDetails.getClientSecret())) {
throw new UnapprovedClientAuthenticationException("clientSecret不匹配");
}
return clientDetails;
}
}