|
@@ -1,6 +1,5 @@
|
|
package com.flow.service.impl;
|
|
package com.flow.service.impl;
|
|
|
|
|
|
-
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
|
import com.flow.common.core.exception.BaseException;
|
|
import com.flow.common.core.exception.BaseException;
|
|
import com.flow.common.core.util.ApplicationContextUtil;
|
|
import com.flow.common.core.util.ApplicationContextUtil;
|
|
@@ -11,26 +10,41 @@ import com.flow.entity.User;
|
|
import com.flow.model.*;
|
|
import com.flow.model.*;
|
|
import com.flow.service.AuthService;
|
|
import com.flow.service.AuthService;
|
|
import com.wf.captcha.ArithmeticCaptcha;
|
|
import com.wf.captcha.ArithmeticCaptcha;
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
+import org.json.JSONObject;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
|
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
|
|
|
+import org.springframework.security.core.Authentication;
|
|
import org.springframework.security.core.context.SecurityContextHolder;
|
|
import org.springframework.security.core.context.SecurityContextHolder;
|
|
|
|
+import org.springframework.security.core.userdetails.UserDetails;
|
|
|
|
+import org.springframework.security.core.userdetails.UserDetailsService;
|
|
|
|
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
|
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
|
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
|
-import org.springframework.security.oauth2.provider.ClientDetails;
|
|
|
|
-import org.springframework.security.oauth2.provider.ClientDetailsService;
|
|
|
|
-import org.springframework.security.oauth2.provider.TokenRequest;
|
|
|
|
|
|
+import org.springframework.security.oauth2.common.exceptions.InvalidGrantException;
|
|
|
|
+import org.springframework.security.oauth2.provider.*;
|
|
import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
|
|
import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
|
|
|
|
+import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
|
|
import org.springframework.security.oauth2.provider.token.TokenStore;
|
|
import org.springframework.security.oauth2.provider.token.TokenStore;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.web.context.request.RequestContextHolder;
|
|
import org.springframework.web.context.request.RequestContextHolder;
|
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
|
+import java.security.KeyFactory;
|
|
|
|
+import java.security.PrivateKey;
|
|
|
|
+import java.security.spec.PKCS8EncodedKeySpec;
|
|
|
|
+import java.util.Base64;
|
|
|
|
+import javax.crypto.Cipher;
|
|
import java.util.*;
|
|
import java.util.*;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
+@Slf4j
|
|
@Service
|
|
@Service
|
|
public class AuthServiceImpl implements AuthService {
|
|
public class AuthServiceImpl implements AuthService {
|
|
|
|
+
|
|
@Autowired
|
|
@Autowired
|
|
private ClientDetailsService clientDetailsService;
|
|
private ClientDetailsService clientDetailsService;
|
|
@Autowired
|
|
@Autowired
|
|
@@ -39,6 +53,26 @@ public class AuthServiceImpl implements AuthService {
|
|
private StringRedisTemplate redisTemplate;
|
|
private StringRedisTemplate redisTemplate;
|
|
@Autowired
|
|
@Autowired
|
|
private AuthDao authDao;
|
|
private AuthDao authDao;
|
|
|
|
+ @Autowired
|
|
|
|
+ private UserDetailsService userDetailsService;
|
|
|
|
+ @Autowired
|
|
|
|
+ private AuthorizationServerTokenServices tokenServices;
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ private static final String PRIVATE_KEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALE9Y/QdMET28R4z\n" +
|
|
|
|
+ "fhDHTdTyhWYLrEipY9G4jm3wnTMQNC50CBco+PLwTRDdxfzTRQ0FPHaBR9FE2s42\n" +
|
|
|
|
+ "oAsoOcnVITqoJQN5c57Pyxr3kZD13gFfulKNkus9+cIFMG1vksaRjnOaWa2kbYBX\n" +
|
|
|
|
+ "14mv6RCqGz+vRziePBoONUbiQXdlAgMBAAECgYBjSDdAXEVYrFdeiouYjHwdyAhP\n" +
|
|
|
|
+ "pERKo5BFvzMRhJIaM353cwnBJ3NkapVQ2Fn6iMIKTB+VZk+7eu1yTAkUluDfLowd\n" +
|
|
|
|
+ "REZS4ipOBY5UuNnjbXmSOoUQw6vRnox0X4x6S1vd4FBHgpVe1VkiE7Nz5U7Clyd5\n" +
|
|
|
|
+ "yw2P1lHwMyB/guAH4QJBAN3dGkMASj0jm23maHOfehp/zlACB8HpMKuV4z/bEg45\n" +
|
|
|
|
+ "nC9Hw5NloUHrXdzEXP1+S46MCH2THflxDVYtnZTRLO0CQQDMgp3Jrn7kkKtNceZF\n" +
|
|
|
|
+ "R08hLbVmfNlatgONgFJ5JnR+GTQ6o2gwM6SLyoBkfAIiEDpr6c6nBXTU09GOYxBk\n" +
|
|
|
|
+ "+h1ZAkB32pXxVBrG5JF20V3j+GcyIZEGz9H5A0xzpUlambIrVRv2vsH8wo5W2hue\n" +
|
|
|
|
+ "w8Woe629mBCOJgevVU9rGsFiP44RAkEApbTYAQjAjJakFpZJjKzg8vNEXoye2R9N\n" +
|
|
|
|
+ "9aOaL8v27A2kAjdRPm050IL+UW0hlVQs4i+KYE7NgX03+PVP3WHD0QJBANLo4PRw\n" +
|
|
|
|
+ "7Y+dLPAzuazsD3/5SYaSh+KSD/+tVbc6CFvLyfFUKp/a4PzzvGaLo/Ky/ffOY5k0\n" +
|
|
|
|
+ "hmavbHCKcg+r+hg=";
|
|
|
|
|
|
@Override
|
|
@Override
|
|
public ImageCode getImageCode() {
|
|
public ImageCode getImageCode() {
|
|
@@ -52,8 +86,102 @@ public class AuthServiceImpl implements AuthService {
|
|
return new ImageCode(captcha.toBase64(), uuid);
|
|
return new ImageCode(captcha.toBase64(), uuid);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // 盐值登录
|
|
|
|
+ @Override
|
|
|
|
+ public AccessToken saltLogin(String salt) {
|
|
|
|
+ AccessToken accessToken = null;
|
|
|
|
+ long now = System.currentTimeMillis();
|
|
|
|
+ String decryptedData = null;
|
|
|
|
+ try {
|
|
|
|
+ decryptedData = decrypt(salt);
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ throw new BaseException("盐值解析异常,请联系管理员" + e.getMessage());
|
|
|
|
+ }
|
|
|
|
+ log.info("解密后的数据: " + decryptedData);
|
|
|
|
+
|
|
|
|
+ if (StringUtils.isBlank(decryptedData)) {
|
|
|
|
+ throw new BaseException("盐值数据为空,请联系管理员");
|
|
|
|
+ } else {
|
|
|
|
+ JSONObject jsonObject = new JSONObject(decryptedData);
|
|
|
|
+
|
|
|
|
+ String user = jsonObject.getString("user");
|
|
|
|
+ long time = jsonObject.getLong("time");
|
|
|
|
+ String form = jsonObject.getString("form");
|
|
|
|
+
|
|
|
|
+ // 判断时间戳是否过期
|
|
|
|
+ // if (now - time < 10000) {
|
|
|
|
+ // throw new BaseException("请求超时,请重试");
|
|
|
|
+ // } else {
|
|
|
|
+ //
|
|
|
|
+ // }
|
|
|
|
+ if (StringUtils.isNotBlank(user)) {
|
|
|
|
+ accessToken = loginByUsername(user);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return accessToken;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // RSA解密
|
|
|
|
+ public String decrypt(String encryptedData) throws Exception {
|
|
|
|
+ String privateKeyBase64 = PRIVATE_KEY.replaceAll("\\s", "");
|
|
|
|
+ // 将Base64编码的私钥转换为PrivateKey对象
|
|
|
|
+ byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyBase64);
|
|
|
|
+
|
|
|
|
+ // 生成PrivateKey对象
|
|
|
|
+ PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
|
|
|
|
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
|
|
|
+ PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
|
|
|
|
+
|
|
|
|
+ // 创建Cipher对象进行解密
|
|
|
|
+ Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
|
|
|
+ cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
|
|
|
+
|
|
|
|
+ // 解密
|
|
|
|
+ encryptedData = encryptedData.replaceAll(" ", "+");
|
|
|
|
+ byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);
|
|
|
|
+ byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
|
|
|
|
+
|
|
|
|
+ // 将解密后的字节转换为字符串
|
|
|
|
+ return new String(decryptedBytes, StandardCharsets.UTF_8);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 获取时间戳
|
|
|
|
+ @Override
|
|
|
|
+ public Long getTimeStamp() {
|
|
|
|
+ return System.currentTimeMillis();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public AccessToken loginByUsername(String username) {
|
|
|
|
+ UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
|
|
|
+
|
|
|
|
+ ClientDetails clientDetails = clientDetailsService.loadClientByClientId("client");
|
|
|
|
+
|
|
|
|
+ // 直接创建OAuth2认证
|
|
|
|
+ OAuth2Request oauth2Request = new OAuth2Request(
|
|
|
|
+ Collections.emptyMap(),
|
|
|
|
+ clientDetails.getClientId(),
|
|
|
|
+ null,
|
|
|
|
+ true,
|
|
|
|
+ clientDetails.getScope(),
|
|
|
|
+ null,
|
|
|
|
+ null,
|
|
|
|
+ null,
|
|
|
|
+ null
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ Authentication userAuth = new UsernamePasswordAuthenticationToken(
|
|
|
|
+ userDetails, null, userDetails.getAuthorities());
|
|
|
|
+
|
|
|
|
+ OAuth2Authentication oauth2Authentication = new OAuth2Authentication(oauth2Request, userAuth);
|
|
|
|
+
|
|
|
|
+ // 直接生成token
|
|
|
|
+ OAuth2AccessToken token = tokenServices.createAccessToken(oauth2Authentication);
|
|
|
|
+ return new AccessToken(token);
|
|
|
|
+ }
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public AccessToken login(LoginForm loginForm) {
|
|
public AccessToken login(LoginForm loginForm) {
|
|
|
|
+ OAuth2AccessToken oAuth2AccessToken = null;
|
|
String uuid = loginForm.getUuid();
|
|
String uuid = loginForm.getUuid();
|
|
String code = loginForm.getCode();
|
|
String code = loginForm.getCode();
|
|
if (StringUtils.isBlank(code) || StringUtils.isBlank(uuid)) {
|
|
if (StringUtils.isBlank(code) || StringUtils.isBlank(uuid)) {
|
|
@@ -66,6 +194,7 @@ public class AuthServiceImpl implements AuthService {
|
|
if (!code.equalsIgnoreCase(redisCode)) {
|
|
if (!code.equalsIgnoreCase(redisCode)) {
|
|
throw new BaseException("验证码错误");
|
|
throw new BaseException("验证码错误");
|
|
}
|
|
}
|
|
|
|
+
|
|
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
|
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
|
request.setAttribute("login_type", "social_login");
|
|
request.setAttribute("login_type", "social_login");
|
|
ClientDetails clientDetails = clientDetailsService.loadClientByClientId("client");
|
|
ClientDetails clientDetails = clientDetailsService.loadClientByClientId("client");
|
|
@@ -78,25 +207,29 @@ public class AuthServiceImpl implements AuthService {
|
|
clientDetails.getClientId(), clientDetails.getScope(),
|
|
clientDetails.getClientId(), clientDetails.getScope(),
|
|
requestParameters.get("grant_type")
|
|
requestParameters.get("grant_type")
|
|
);
|
|
);
|
|
- ResourceOwnerPasswordTokenGranter granter = ApplicationContextUtil.getBean(ResourceOwnerPasswordTokenGranter.class);
|
|
|
|
- OAuth2AccessToken oAuth2AccessToken = granter.grant(tokenRequest.getGrantType(), tokenRequest);
|
|
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ ResourceOwnerPasswordTokenGranter granter = ApplicationContextUtil.getBean(ResourceOwnerPasswordTokenGranter.class);
|
|
|
|
+ oAuth2AccessToken = granter.grant(tokenRequest.getGrantType(), tokenRequest);
|
|
|
|
+ } catch (InvalidGrantException ex) {
|
|
|
|
+ throw new BaseException("用户名或密码错误");
|
|
|
|
+ }
|
|
|
|
+
|
|
return new AccessToken(oAuth2AccessToken);
|
|
return new AccessToken(oAuth2AccessToken);
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|
|
public void logout() {
|
|
public void logout() {
|
|
- try {
|
|
|
|
- String accessToken = SecurityContextUtil.getAccessToken();
|
|
|
|
- if (StringUtils.isNotBlank(accessToken)) {
|
|
|
|
- OAuth2AccessToken oAuth2AccessToken = tokenStore.readAccessToken(SecurityContextUtil.getAccessToken());
|
|
|
|
- tokenStore.removeAccessToken(oAuth2AccessToken);
|
|
|
|
- if (Objects.nonNull(oAuth2AccessToken.getRefreshToken())) {
|
|
|
|
- tokenStore.removeRefreshToken(oAuth2AccessToken.getRefreshToken());
|
|
|
|
- }
|
|
|
|
- SecurityContextHolder.getContext().setAuthentication(null);
|
|
|
|
- SecurityContextHolder.clearContext();
|
|
|
|
|
|
+ String accessToken = SecurityContextUtil.getAccessToken();
|
|
|
|
+ if (StringUtils.isNotBlank(accessToken)) {
|
|
|
|
+ OAuth2AccessToken oAuth2AccessToken = tokenStore.readAccessToken(SecurityContextUtil.getAccessToken());
|
|
|
|
+ tokenStore.removeAccessToken(oAuth2AccessToken);
|
|
|
|
+ if (Objects.nonNull(oAuth2AccessToken.getRefreshToken())) {
|
|
|
|
+ tokenStore.removeRefreshToken(oAuth2AccessToken.getRefreshToken());
|
|
}
|
|
}
|
|
- } catch (Exception ignored) {}
|
|
|
|
|
|
+ SecurityContextHolder.getContext().setAuthentication(null);
|
|
|
|
+ SecurityContextHolder.clearContext();
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
@Override
|
|
@Override
|