Commit 3122d943 authored by Administrator's avatar Administrator

开发提测

parent 8393b9f1
##启动项: ##启动项:
-Denv=dev -Didc=k8s -Dserver.port=8099 -DNAMESPACE=test1 -Denv=dev -Didc=k8s -Dserver.port=8099 -DNAMESPACE=test1
##登录头信息
headers: {
Authorization: `Basic ${encodedUserInfo}`,
'x-real-ip': ip,
idfa,
scDeviceId,
'x-user-platform': utils.getPlatform({headers: {appchannel: appChannel}}),
'x-user-phone': username
}
\ No newline at end of file
KA-4/2021-06-30
...@@ -15,6 +15,21 @@ ...@@ -15,6 +15,21 @@
<name>xyqb-user2</name> <name>xyqb-user2</name>
<description>xyqb web application</description> <description>xyqb web application</description>
<profiles>
<profile>
<id>dev</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>1.5.8.RELEASE</version>
<optional>true</optional>
<scope>true</scope>
</dependency>
</dependencies>
</profile>
</profiles>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version> <java.version>1.8</java.version>
...@@ -407,6 +422,9 @@ ...@@ -407,6 +422,9 @@
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
......
package cn.quantgroup.xyqb.config;
import cn.quantgroup.xyqb.security.AuthenticationAdapter;
import cn.quantgroup.xyqb.security.AuthenticationPrincipal;
import cn.quantgroup.xyqb.security.CustomerAuthenticationManager;
import cn.quantgroup.xyqb.urora.UroraAuthenticationManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import static cn.quantgroup.xyqb.security.SecurityConstant.PROPERTY_PREFIX;
/**
* Created by Administrator on 2021/7/1 0001.
*/
@Configuration
@EnableConfigurationProperties(AuthenticationConfigurationProperties.class)
public class AuthenticationConfiguration {
private static final Logger logger = LoggerFactory.getLogger(AuthenticationConfiguration.class);
@Bean
public AuthenticationAdapter authenticationAdapter(AuthenticationConfigurationProperties properties) {
AuthenticationAdapter adapter = new AuthenticationAdapter();
Map<String, Map<String, String>> manager = properties.getManager();
Set<String> strings = manager.keySet();
try {
for (String key : strings) {
Map<String, String> map = manager.get(key);
Class<?> target = Thread.currentThread().getContextClassLoader().loadClass(map.get("target"));
//TODO: wait bean bean definition authentication manager
CustomerAuthenticationManager instance = (CustomerAuthenticationManager) target.newInstance();
instance.setPrincipal(new AuthenticationPrincipal(key));
Properties prop = new Properties();
map.forEach((k, v) -> {
if (k.startsWith(PROPERTY_PREFIX)) {
prop.setProperty(k.substring(PROPERTY_PREFIX.length()), v);
}
});
instance.setProperties(prop);
if (UroraAuthenticationManager.class.isInstance(instance)) {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setReadTimeout(Integer.parseInt(prop.getProperty("readTimeout", "10000")));
factory.setConnectTimeout(Integer.parseInt(prop.getProperty("connectTimeout", "20000")));
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(factory);
((UroraAuthenticationManager) instance).setRestTemplate(restTemplate);
}
instance.init();
logger.info("Authentication adapter register manager. {} - properties:{}", target, prop);
adapter.register(instance);
}
} catch (Exception e) {
logger.error("Authentication configuration initialization failed. " + e.getMessage(), e);
}
return adapter;
}
}
package cn.quantgroup.xyqb.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Administrator on 2021/7/1 0001.
*/
@ConfigurationProperties(
prefix = "user.auth"
)
public class AuthenticationConfigurationProperties {
private Map<String, Map<String, String>> manager = new HashMap<>();
public Map<String, Map<String, String>> getManager() {
return manager;
}
public void setManager(Map<String, Map<String, String>> manager) {
this.manager = manager;
}
}
package cn.quantgroup.xyqb.controller.external; package cn.quantgroup.xyqb.controller.external;
import cn.quantgroup.xyqb.Constants; import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.security.AuthorizationPoint;
import cn.quantgroup.xyqb.aspect.accessable.IpValidator; import cn.quantgroup.xyqb.aspect.accessable.IpValidator;
import cn.quantgroup.xyqb.aspect.captcha.CaptchaFiniteValidator; import cn.quantgroup.xyqb.aspect.captcha.CaptchaFiniteValidator;
import cn.quantgroup.xyqb.aspect.captcha.LoginInterceptor; import cn.quantgroup.xyqb.aspect.captcha.LoginInterceptor;
...@@ -45,7 +46,6 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -45,7 +46,6 @@ import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.*; import java.util.*;
...@@ -84,6 +84,9 @@ public class UserController implements IBaseController { ...@@ -84,6 +84,9 @@ public class UserController implements IBaseController {
@Autowired @Autowired
private IUserRegisterService userRegisterService; private IUserRegisterService userRegisterService;
/** /**
* 登录(账号 + 密码) * 登录(账号 + 密码)
* 密码错误达到限定次数时执行图形验证码校验 * 密码错误达到限定次数时执行图形验证码校验
......
...@@ -10,6 +10,8 @@ import cn.quantgroup.xyqb.model.JsonResult; ...@@ -10,6 +10,8 @@ import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.LoginProperties; import cn.quantgroup.xyqb.model.LoginProperties;
import cn.quantgroup.xyqb.model.UserRet; import cn.quantgroup.xyqb.model.UserRet;
import cn.quantgroup.xyqb.model.session.LoginInfo; import cn.quantgroup.xyqb.model.session.LoginInfo;
import cn.quantgroup.xyqb.security.AuthorityManager;
import cn.quantgroup.xyqb.security.AuthorizationPoint;
import cn.quantgroup.xyqb.service.merchant.IMerchantService; import cn.quantgroup.xyqb.service.merchant.IMerchantService;
import cn.quantgroup.xyqb.service.register.IUserRegisterService; import cn.quantgroup.xyqb.service.register.IUserRegisterService;
import cn.quantgroup.xyqb.service.session.ISessionService; import cn.quantgroup.xyqb.service.session.ISessionService;
...@@ -19,6 +21,8 @@ import cn.quantgroup.xyqb.util.ValidationUtil; ...@@ -19,6 +21,8 @@ import cn.quantgroup.xyqb.util.ValidationUtil;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
...@@ -48,6 +52,60 @@ public class AppController implements IBaseController { ...@@ -48,6 +52,60 @@ public class AppController implements IBaseController {
@Autowired @Autowired
private IUserRegisterService userRegisterService; private IUserRegisterService userRegisterService;
@IpValidator
@AuthorizationPoint
@RequestMapping("/auth/v1/login")
public JsonResult authLoginV1(
String idNo
, String name
, @RequestParam(required = true) String key,
@RequestParam(required = true) Long createdFrom,
@RequestParam(required = true) Long registerFrom,
@RequestParam(required = true) Long channelId,
@RequestParam(required = true) String appChannel,
HttpServletRequest request) {
JsonResult result = null;
Authentication authentication = AuthorityManager.authentication();
if(authentication.isAuthenticated()){
String phoneNumber = ObjectUtils.getDisplayString(authentication.getCredentials());
if (!ValidationUtil.validatePhoneNo(phoneNumber)) {
result = JsonResult.buildErrorStateResult(USER_ERROR_OR_PASSWORD_ERROR, null);
}else{
User user = userService.findByPhoneInDb(phoneNumber);
if (user == null) {
user = userRegisterService.register(registerFrom, phoneNumber, idNo, name, channelId, createdFrom);
}
if (user == null) {
result = JsonResult.buildErrorStateResult(USER_ERROR_OR_PASSWORD_ERROR, null);
} else if (!user.getEnable()) {
result = JsonResult.buildErrorStateResult("登录失败", null);
} else {
Merchant merchant = merchantService.findMerchantByName(key);
if (merchant == null) {
result = JsonResult.buildErrorStateResult("无效的商户", null);
}else{
LoginProperties loginProperties = new LoginProperties("", 4, channelId, registerFrom, appChannel, merchant.getId(), merchant.getName());
AuthBean bean = sessionService.createSession(user, loginProperties);
LoginInfo.LoginContext context = new LoginInfo.LoginContext();
context.setChannelId(channelId);
context.setCreatedFrom(registerFrom);
context.setAppChannel(appChannel);
LoginInfo loginInfo = new LoginInfo();
loginInfo.setUser(new UserRet(user));
loginInfo.setHasPassword(user.getHasPassword());
loginInfo.setToken(bean.getToken());
loginInfo.setLoginContext(context);
result = JsonResult.buildSuccessResult("登陆成功", loginInfo);
}
}
}
}else{
result = JsonResult.buildErrorStateResult("登录失败", null);
}
return result;
}
/** /**
* 第三方用户免密登录 * 第三方用户免密登录
* 发现新手机号,自动执行注册 * 发现新手机号,自动执行注册
...@@ -62,8 +120,8 @@ public class AppController implements IBaseController { ...@@ -62,8 +120,8 @@ public class AppController implements IBaseController {
* @param appChannel - 应用平台(应用商店、AppStore...) * @param appChannel - 应用平台(应用商店、AppStore...)
* @param request * @param request
* @return Token和phoneNo * @return Token和phoneNo
* @yapi http://yapi.quantgroups.com/project/17/interface/api/169 * @yapi http://yapi.quantgroups.com/project/17/interface/api/169
* @Deprecated 20210318 * @Deprecated 20210318
*/ */
@Deprecated @Deprecated
@IpValidator @IpValidator
...@@ -115,7 +173,7 @@ public class AppController implements IBaseController { ...@@ -115,7 +173,7 @@ public class AppController implements IBaseController {
* @param appChannel - 应用平台(应用商店、AppStore...) * @param appChannel - 应用平台(应用商店、AppStore...)
* @param request * @param request
* @return 用户信息 * @return 用户信息
* @yapi http://yapi.quantgroups.com/project/17/interface/api/173 * @yapi http://yapi.quantgroups.com/project/17/interface/api/173
*/ */
@IpValidator @IpValidator
@RequestMapping("/login_super") @RequestMapping("/login_super")
...@@ -170,13 +228,13 @@ public class AppController implements IBaseController { ...@@ -170,13 +228,13 @@ public class AppController implements IBaseController {
* 第三方用户免密登录 * 第三方用户免密登录
* 发现新手机号不会执行注册 * 发现新手机号不会执行注册
* *
* @param phoneNo - 手机号 * @param phoneNo - 手机号
* @param registerFrom - 注册渠道(第一次用户来源channelId) * @param registerFrom - 注册渠道(第一次用户来源channelId)
* @param channelId - 渠道 * @param channelId - 渠道
* @param appChannel - 应用平台(应用商店、AppStore...) * @param appChannel - 应用平台(应用商店、AppStore...)
* @param request * @param request
* @return Token和phoneNo * @return Token和phoneNo
* @yapi http://yapi.quantgroups.com/project/17/interface/api/171 * @yapi http://yapi.quantgroups.com/project/17/interface/api/171
*/ */
@LoginInterceptor @LoginInterceptor
@IpValidator @IpValidator
......
...@@ -8,8 +8,7 @@ public enum Device { ...@@ -8,8 +8,7 @@ public enum Device {
ANDROID("安卓", "android"), ANDROID("安卓", "android"),
IOS("IOS", "ios"), IOS("IOS", "ios"),
OTHER("other","other"), OTHER("other", "other");
;
private String desc; private String desc;
private String code; private String code;
...@@ -19,8 +18,8 @@ public enum Device { ...@@ -19,8 +18,8 @@ public enum Device {
this.code = code; this.code = code;
} }
public static Device valueOfCode(String code) { public static Device valueOfCode(String code) {
if(null == code){ if (null == code || "".equals(code)) {
return Device.OTHER; return Device.OTHER;
} }
for (Device device : Device.values()) { for (Device device : Device.values()) {
......
package cn.quantgroup.xyqb.security;
import cn.quantgroup.xyqb.entity.enums.Device;
import java.util.Objects;
/**
* Created by Administrator on 2021/6/30 0030.
*/
public class AssentHeader {
String authType;
String authMessage;
String idfa;
String scDeviceId;
String remoteAddress;
String phoneNumber;
String deviceId;
String deviceCode;
Device device;
public String getAuthType() {
return authType;
}
public void setAuthType(String authType) {
this.authType = authType;
}
public String getAuthMessage() {
return authMessage;
}
public void setAuthMessage(String authMessage) {
this.authMessage = authMessage;
}
public String getIdfa() {
return idfa;
}
public void setIdfa(String idfa) {
this.idfa = idfa;
}
public String getScDeviceId() {
return scDeviceId;
}
public void setScDeviceId(String scDeviceId) {
this.scDeviceId = scDeviceId;
}
public String getRemoteAddress() {
return remoteAddress;
}
public void setRemoteAddress(String remoteAddress) {
this.remoteAddress = remoteAddress;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getDeviceCode() {
return deviceCode;
}
public void setDeviceCode(String deviceCode) {
this.deviceCode = deviceCode;
}
public Device getDevice() {
return device;
}
public void setDevice(Device device) {
this.device = device;
}
@Override
public int hashCode() {
return com.google.common.base.Objects.hashCode(authType, authMessage, idfa, scDeviceId, remoteAddress
, phoneNumber, deviceId, deviceCode, device);
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("AssentHeader{");
sb.append("authType='").append(authType).append('\'');
sb.append(", authMessage='").append(authMessage).append('\'');
sb.append(", idfa='").append(idfa).append('\'');
sb.append(", scDeviceId='").append(scDeviceId).append('\'');
sb.append(", remoteAddress='").append(remoteAddress).append('\'');
sb.append(", phoneNumber='").append(phoneNumber).append('\'');
sb.append(", deviceId='").append(deviceId).append('\'');
sb.append(", deviceCode='").append(deviceCode).append('\'');
sb.append(", device=").append(device);
sb.append('}');
return sb.toString();
}
}
package cn.quantgroup.xyqb.security;
import cn.quantgroup.xyqb.service.session.ISessionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Administrator on 2021/7/1 0001.
*/
public class AuthenticationAdapter {
public Map<String, CustomerAuthenticationManager> managers = new HashMap<>();
public AuthenticationAdapter() {
}
public void register(CustomerAuthenticationManager manager) {
managers.put(manager.getPrincipal().getName(), manager);
}
public CustomerAuthenticationManager getManager(String name){
return managers.get(name);
}
public Authentication authenticate(String principal, String credentials){
CustomerAuthenticationManager authenticationManager = getManager(principal);
if(authenticationManager==null){
throw new IllegalArgumentException("No such authentication manager. "+principal);
}
Authentication authenticate = authenticationManager.authenticate(credentials);
return authenticate;
}
}
package cn.quantgroup.xyqb.security;
import javax.security.auth.Subject;
import java.security.Principal;
/**
* Created by Administrator on 2021/7/1 0001.
*/
public class AuthenticationPrincipal implements Principal {
private String name;
public AuthenticationPrincipal(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public boolean implies(Subject subject) {
return false;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof String) {
return getName().equals((String) obj);
}
if (obj instanceof Principal)
return getName().equals(((Principal) obj).getName());
return false;
}
}
package cn.quantgroup.xyqb.security;
import org.springframework.security.core.Authentication;
/**
* Created by Administrator on 2021/7/3 0003.
*/
public final class AuthorityManager {
private static final ThreadLocal<Authentication> authenticationThreadLocal = new ThreadLocal<>();
static final void authentication(Authentication authentication){
authenticationThreadLocal.set(authentication);
}
public static final Authentication authentication(){
return authenticationThreadLocal.get();
}
static final void release(){
authenticationThreadLocal.remove();
}
}
package cn.quantgroup.xyqb.security;
import cn.qg.ec.model.user.UserLoginRegEvent;
import cn.quantgroup.xyqb.service.event.KinesisService;
import cn.quantgroup.xyqb.urora.UroraAuthenticationManager;
import cn.quantgroup.xyqb.urora.UroraAuthenticationToken;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
/**
* Created by Administrator on 2021/6/25 0025.
*/
@Aspect
@Component
public class AuthorizationAspect extends HttpAspect {
private static final Logger logger = LoggerFactory.getLogger(AuthorizationAspect.class);
@Autowired
private AuthenticationAdapter authenticationAdapter;
@Pointcut("@annotation(cn.quantgroup.xyqb.security.AuthorizationPoint)")
private void pointCut() {
}
@Around("pointCut()")
private Object around(ProceedingJoinPoint joinPoint) throws Throwable {
AssentHeader header = getAssentHeader();
// kinesisService.send(UserLoginRegEvent.SubEventType.user_attempt_login, header, null);
Authentication authenticate = authenticationAdapter.authenticate(header.getAuthType(), header.getAuthMessage());
if(!authenticate.isAuthenticated()){
throw new BadCredentialsException("not authorized");
}
AuthorityManager.authentication(authenticate);
try {
Object object = joinPoint.proceed();
return object;
}finally {
AuthorityManager.release();
}
}
}
package cn.quantgroup.xyqb.security;
import java.lang.annotation.*;
/**
* Created by Administrator on 2021/6/25 0025.
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthorizationPoint {
}
package cn.quantgroup.xyqb.security;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.util.StringUtils;
import java.security.Principal;
import java.util.Properties;
/**
* Created by Administrator on 2021/7/1 0001.
*/
public abstract class CustomerAuthenticationManager implements AuthenticationManager {
private Principal principal;
private Properties properties = new Properties();
public CustomerAuthenticationManager() {
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public String getProperty(String key) {
return properties.getProperty(key);
}
public void setPrincipal(Principal principal) {
this.principal = principal;
}
public Principal getPrincipal() {
return principal;
}
public Authentication authenticate(String credentials) throws AuthenticationException {
Authentication auth = getCredentials(credentials);
if (StringUtils.isEmpty(auth.getPrincipal()) || StringUtils.isEmpty(auth.getCredentials())) {
throw new BadCredentialsException("authorization credentials does not look like urora. " + auth);
}
auth = authenticate(auth);
return auth;
}
public abstract void init();
public abstract Authentication getCredentials(String message) throws AuthenticationException;
public abstract Authentication authenticate(Authentication authentication) throws AuthenticationException;
}
package cn.quantgroup.xyqb.security;
import cn.quantgroup.xyqb.entity.enums.Device;
import cn.quantgroup.xyqb.exception.DataException;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import static cn.quantgroup.xyqb.security.SecurityConstant.DEFAULT_DEVICE_ID;
/**
* Created by Administrator on 2021/6/30 0030.
*/
public abstract class HttpAspect {
public AssentHeader getAssentHeader() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
AssentHeader header = new AssentHeader();
String authorization = ObjectUtils.getDisplayString(request.getHeader("authorization"));
if(!StringUtils.isEmpty(authorization)){
String[] strings = authorization.split(" ");
if(strings.length<2){
throw new DataException("Header does not look like authorization. "+authorization);
}
header.setAuthType(strings[0]);
header.setAuthMessage(strings[1]);
}
header.setIdfa(ObjectUtils.getDisplayString(request.getHeader("idfa")));
header.setScDeviceId(ObjectUtils.getDisplayString(request.getHeader("scDeviceId")));
header.setRemoteAddress(ObjectUtils.getDisplayString(request.getHeader("x-real-ip")));
header.setDeviceCode(ObjectUtils.getDisplayString(request.getHeader("x-user-platform")));
header.setPhoneNumber(ObjectUtils.getDisplayString(request.getHeader("x-user-phone")));
header.setDeviceId(DEFAULT_DEVICE_ID);
if (!"".equals(header.getScDeviceId())) {
header.setDeviceId(header.getScDeviceId());
} else if (!"".equals(header.getIdfa())) {
header.setDeviceId(header.getIdfa());
}
header.setDevice(Device.valueOfCode(header.getDeviceCode()));
return header;
}
}
package cn.quantgroup.xyqb.security;
import javax.crypto.Cipher;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
/**
* Created by Administrator on 2021/7/5 0005.
*/
public class RSADecrypt {
public static void main(String[] args) throws Exception {
String encrypted = args[0];
String prikey = args[1];
String result = decrypt(encrypted, prikey);
System.out.println(result);
}
public static String decrypt(String cryptograph, String prikey) throws Exception {
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(prikey));
PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);
Cipher cipher=Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte [] b = Base64.getDecoder().decode(cryptograph);
return new String(cipher.doFinal(b));
}
}
package cn.quantgroup.xyqb.security;
/**
* Created by Administrator on 2021/7/1 0001.
*/
public class SecurityConstant {
public static final String DEFAULT_DEVICE_ID = "00000000-0000-0000-0000-000000000000";
public static final String PROPERTY_PREFIX = "properties.";
}
package cn.quantgroup.xyqb.service;
import cn.quantgroup.xyqb.entity.enums.Device;
import cn.quantgroup.xyqb.model.LoginRefuseResult;
import cn.quantgroup.xyqb.risk.repository.LoginInfoRepository;
import cn.quantgroup.xyqb.risk.repository.WhiteListRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import static cn.quantgroup.xyqb.security.SecurityConstant.DEFAULT_DEVICE_ID;
/**
* Created by Administrator on 2021/7/1 0001.
*/
@Service
public class LoginInfoService {
private static final Logger logger = LoggerFactory.getLogger(LoginInfoService.class);
@Autowired
private LoginInfoRepository loginInfoRepository;
@Autowired
private WhiteListRepository whiteListRepository;
private LoginRefuseResult verification(String deviceId, String phone, Device device) {
/**
* 默认code不需要
*/
if (DEFAULT_DEVICE_ID.equals(deviceId)) {
return LoginRefuseResult.builder()
.isPass(Boolean.TRUE).build();
}
/**
* 如果没传手机也放过吧
*/
if (StringUtils.isEmpty(phone)) {
return LoginRefuseResult.builder()
.isPass(Boolean.TRUE).build();
}
// try {
// /**
// * 阈值
// */
// Long threshold = DEVICE_REFUSE_STRATEGY.get(device);
//
// if (null == threshold) {
// log.warn("非安卓或者IOS设备登录没有策略就放过phone:{},device:{}", phone, device);
// return LoginRefuseResult.builder()
// .isPass(Boolean.TRUE).build();
// }
//
// Long deviceNum = loginInfoRepository.countByDeviceId(deviceId, phone);
//
// if (DEVICE_REFUSE_COUNT.compareTo(deviceNum) <= 0) {
// if (!isWhite(deviceId, KeyType.DEVICEID)) {
// log.warn("此设备登录命中拒绝策略deviceId:{}超过{}个拒绝登录", deviceId, deviceNum);
// return LoginRefuseResult.builder()
// .isPass(Boolean.FALSE)
// .rule(RISK_STRATEGY[0])
// .threshold(DEVICE_REFUSE_COUNT.intValue())
// .value(deviceNum.intValue())
// .build();
// }
//
// }
//
// CountDevice countDevice = loginInfoRepository.countByPhoneAndDevice(phone, device.ordinal(), deviceId);
//
// if (null == countDevice) {
// return LoginRefuseResult.builder()
// .isPass(Boolean.TRUE)
// .build();
// }
// /**
// * 实际的数量
// */
// Long val = countDevice.getNum();
//
// if (threshold.compareTo(val) <= 0) {
// if (!isWhite(phone, KeyType.PHONE)) {
// log.warn("此账户登录命中拒绝策略并且没有白名单phone:{},device:{}", phone, device);
// return LoginRefuseResult.builder()
// .isPass(Boolean.FALSE)
// .rule(RISK_STRATEGY[1])
// .threshold(threshold.intValue())
// .value(Long.valueOf(val).intValue())
// .build();
// }
// log.warn("此账户登录命中拒绝策略存在白名单phone:{}", phone);
// }
// } catch (Exception e) {
// log.error("用户登录策略校验异常了", e);
// }
// return LoginRefuseResult.builder()
// .isPass(Boolean.TRUE)
// .build();
return null;
}
}
package cn.quantgroup.xyqb.service.event;
import cn.qg.ec.model.base.BusinessEventBaseInfo;
import cn.qg.ec.model.user.UserLoginRegEvent;
import cn.quantgroup.xyqb.entity.User;
import cn.quantgroup.xyqb.security.AssentHeader;
import cn.quantgroup.xyqb.model.AuthBean;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.risk.uereventcollecting.UserEventCollectingUtil;
import cn.quantgroup.xyqb.service.user.IUserService;
import cn.quantgroup.xyqb.util.encrypt.Md5Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
/**
* Created by Administrator on 2021/6/30 0030.
*/
@Service
public class KinesisService {
private static final Logger logger = LoggerFactory.getLogger(KinesisService.class);
@Resource
private IUserService iUserService;
public void send(UserLoginRegEvent.SubEventType type, AssentHeader header, Object loginResult) {
String phoneNumber = header.getPhoneNumber();
if (StringUtils.isEmpty(phoneNumber)) {
return;
}
long nanoTime = System.nanoTime();
try {
logger.info(">>>> KNS-PRDR-B -- {}; .TP={}; .PN={}; .DCID={}; .CONT={}", nanoTime, type, header.getPhoneNumber(), header.getDeviceId(), header);
UserLoginRegEvent.UserLoginRegEventBuilder builder = UserLoginRegEvent.builder();
builder.maskPhoneNo(phoneNumber);
builder.hashPhoneNo(Md5Util.build(Md5Util.build(phoneNumber)));
builder.subEventType(type);
BusinessEventBaseInfo.BusinessEventBaseInfoBuilder baseInfoBuilder
= BusinessEventBaseInfo.builder();
if (null != loginResult) {
if (loginResult instanceof JsonResult) {
JsonResult jsonResult = ((JsonResult) loginResult);
if (jsonResult.isSuccess()) {
Object data = jsonResult.getData();
if (data instanceof AuthBean) {
String uuid = ((AuthBean) data).getUuid();
User user = iUserService.findByUuidWithCache(uuid);
baseInfoBuilder.userUuid(uuid);
baseInfoBuilder.channel(String.valueOf(user.getRegisteredFrom()));
} else {
return;
}
} else {
return;
}
}
}
baseInfoBuilder.deviceId(header.getDeviceId());
baseInfoBuilder.ip(header.getRemoteAddress());
baseInfoBuilder.deviceType(header.getDevice().getCode());
builder.businessEventBaseInfo(baseInfoBuilder.build());
UserEventCollectingUtil.addEvent(builder.build());
logger.info("++ KNS-PRDR -- {}; .CONT={}", nanoTime, builder.toString());
} catch (Exception e) {
logger.error("!! KNS-PRDR-E -- " + nanoTime + "; .CONT=" + e.getMessage(), e);
throw e;
} finally {
logger.info("<<<< KNS-PRDR-F -- {}", nanoTime);
}
}
}
...@@ -27,7 +27,7 @@ import java.util.UUID; ...@@ -27,7 +27,7 @@ import java.util.UUID;
*/ */
@Service("userRegisterService") @Service("userRegisterService")
@Slf4j @Slf4j
public class UserRegisterServiceImpl implements IUserRegisterService { public class UserRegisterServiceImpl implements IUserRegisterService {
@Resource @Resource
private ApplicationEventPublisher applicationEventPublisher; private ApplicationEventPublisher applicationEventPublisher;
......
...@@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit; ...@@ -26,6 +26,7 @@ import java.util.concurrent.TimeUnit;
/** /**
* session创建和续期 * session创建和续期
*
*/ */
@Slf4j @Slf4j
@Service @Service
...@@ -45,6 +46,7 @@ public class SessionServiceImpl implements ISessionService { ...@@ -45,6 +46,7 @@ public class SessionServiceImpl implements ISessionService {
@Override @Override
public AuthBean createSession(User user, LoginProperties properties) { public AuthBean createSession(User user, LoginProperties properties) {
//找到用户 //找到用户
//TODO: 使用userId
String sessionId = findSessionIdByUserIdLoginProperties(user.getId(), properties); String sessionId = findSessionIdByUserIdLoginProperties(user.getId(), properties);
SessionStruct sessionStruct = null; SessionStruct sessionStruct = null;
if (StringUtils.isNotEmpty(sessionId)) { if (StringUtils.isNotEmpty(sessionId)) {
......
package cn.quantgroup.xyqb.urora;
import cn.quantgroup.xyqb.security.CustomerAuthenticationManager;
import cn.quantgroup.xyqb.security.RSADecrypt;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.*;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
import java.util.List;
/**
* Created by Administrator on 2021/7/1 0001.
*/
public class UroraAuthenticationManager extends CustomerAuthenticationManager {
private static final Logger logger = LoggerFactory.getLogger(UroraAuthenticationManager.class);
private RestTemplate restTemplate;
private HttpHeaders headers;
public RestTemplate getRestTemplate() {
return restTemplate;
}
public void setRestTemplate(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Override
public void init() {
this.headers = new HttpHeaders();
this.headers.add("Authorization", getProperty("authorization"));
this.headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters();
MappingJackson2HttpMessageConverter stringHttpMessageConverter = new MappingJackson2HttpMessageConverter();
stringHttpMessageConverter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_UTF8, MediaType.TEXT_PLAIN));
messageConverters.add(stringHttpMessageConverter);
}
@Override
public Authentication getCredentials(String credentials) throws AuthenticationException {
String auth = ObjectUtils.getDisplayString(credentials);
if (StringUtils.isEmpty(credentials)) {
throw new BadCredentialsException("Authorization credentials does not look like urora. " + credentials);
}
auth = new String(Base64.decodeBase64(auth));
String[] strings = auth.split(":");
if (strings.length != 2) {
throw new BadCredentialsException("Authorization credentials does not look like urora. " + auth);
}
return new UroraAuthenticationToken(strings[0], strings[1]);
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
HttpEntity<String> httpEntity = new HttpEntity<>("{\"loginToken\":\"" + authentication.getCredentials() + "\"}", headers);
try {
ResponseEntity<UroraResponse> verify = restTemplate.postForEntity(getProperty("loginTokenVerify"), httpEntity, UroraResponse.class);
if (HttpStatus.OK.equals(verify.getStatusCode())) {
UroraResponse body = verify.getBody();
if (!body.getCode().equals("8000") || StringUtils.isEmpty(body.getPhone())) {
authentication.setAuthenticated(false);
} else {
String decrypt = RSADecrypt.decrypt(body.getPhone(), getProperty("privateKey"));
UroraAuthenticationToken token = new UroraAuthenticationToken(body.getId(), decrypt);
token.setAuthenticated(true);
return token;
}
}
} catch (Exception e) {
logger.error("Urora login token verify failed. " + e.getMessage(), e);
authentication.setAuthenticated(false);
}
return authentication;
}
}
\ No newline at end of file
package cn.quantgroup.xyqb.urora;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import java.util.Collection;
/**
* Created by Administrator on 2021/7/1 0001.
*/
public class UroraAuthenticationToken extends AbstractAuthenticationToken {
private final Object principal;
private Object credentials;
public UroraAuthenticationToken(Object principal) {
this(principal, null);
}
public UroraAuthenticationToken(Object principal, Object credentials) {
super((Collection) null);
this.principal = principal;
this.credentials = credentials;
this.setAuthenticated(false);
}
@Override
public Object getCredentials() {
return credentials;
}
@Override
public Object getPrincipal() {
return principal;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("UroraAuthenticationToken{");
sb.append("principal=").append(principal);
sb.append(", credentials=").append(credentials);
sb.append(',').append(super.toString());
sb.append('}');
return sb.toString();
}
}
package cn.quantgroup.xyqb.urora;
/**
* Created by Administrator on 2021/7/5 0005.
*/
public class UroraResponse {
private Long id;
private String code;
private String content;
private String phone;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("UroraResponse{");
sb.append("id=").append(id);
sb.append(", code='").append(code).append('\'');
sb.append(", content='").append(content).append('\'');
sb.append(", phone='").append(phone).append('\'');
sb.append('}');
return sb.toString();
}
}
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8"?>
<configuration>
<springProperty name="spring.application.name" source="spring.application.name"/>
<property name="LOG_LEVEL_PATTERN" value="%clr(%5p) %clr([${spring.application.name:-},%X{X-B3-TraceId:-},%X{X-B3-SpanId:-},%X{X-Span-Export:-}]){yellow}"/>
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%10.10t]){faint} [%40.40file:%4.4line] %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<!-- 这里面定义了 CONSOLE_LOG_PATTERN, FILE_LOG_PATTERN 等日志格式, 还定义了一些日志级别 --> <configuration scan="true">
<include resource="org/springframework/boot/logging/logback/defaults.xml" />
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
<logger name="cn.quantgroup" level="DEBUG" /> <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<logger name="org.springframework" level="INFO" /> <resetJUL>true</resetJUL>
<!--<logger name="java.sql.Connection" level="DEBUG"/>--> </contextListener>
<!--<logger name="java.sql.Statement" level="DEBUG"/>-->
<!--<logger name="java.sql.PreparedStatement" level="DEBUG"/>-->
<logger name="org.hibernate" level="warn"/>
<logger name="org.apache" level="warn"/>
<logger name="ch.qos.logback" level="warn"/>
<logger name="com.amazonaws.services.kinesis.producer.LogInputStreamReader" level="warn"/>
<root level="INFO"> <appender name="ROLLINGFILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<appender-ref ref="CONSOLE" /> <file>./xyqb-user2.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>./xyqb-user2.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>90</maxHistory>
</rollingPolicy>
<encoder>
<charset>utf-8</charset>
<Pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}][%p][%X{sessionId}][%X{traceId}][${spring.profiles.active}][%X{userId}][%t|%logger{1.}|%M|%X{ctime}] - %msg %ex{full}%n</Pattern>
</encoder>
</appender>
<appender name="ASYNC_ROLLINGFILE" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>512</queueSize>
<appender-ref ref="ROLLINGFILE"/>
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}]%-4relative [%thread] %-5level %logger{35} - %msg %ex{full}%n</pattern>
</encoder>
</appender>
<!--<logger name="javax.activation" level="ERROR"/>-->
<!--<logger name="org.quartz.core" level="ERROR"/>-->
<!--<logger name="org.quartz.simpl" level="ERROR"/>-->
<!--<logger name="com.zaxxer.hikari.pool" level="ERROR"/>-->
<!--<logger name="com.alibaba.dubbo.common.extension" level="ERROR"/>-->
<!--<logger name="org.apache.zookeeper" level="ERROR"/>-->
<!--<logger name="org.apache.curator" level="ERROR"/>-->
<!--<logger name="org.apache.catalina.loader" level="ERROR"/>-->
<!--<logger name="org.apache.catalina.util" level="ERROR"/>-->
<!--<logger name="org.apache.catalina.core" level="ERROR"/>-->
<!--<logger name="org.hibernate.hql" level="ERROR"/>-->
<!--<logger name="org.hibernate.loader" level="ERROR"/>-->
<!--<logger name="org.hibernate.type" level="ERROR"/>-->
<!--<logger name="org.hibernate.persister" level="ERROR"/>-->
<!--<logger name="org.hibernate.cfg" level="ERROR"/>-->
<!--<logger name="org.hibernate.mapping" level="ERROR"/>-->
<!--<logger name="org.hibernate.jpa.event" level="ERROR"/>-->
<!--<logger name="org.hibernate.validator.internal" level="ERROR"/>-->
<!--<logger name="org.hibernate.engine.internal" level="ERROR"/>-->
<!--<logger name="org.hibernate.boot.model" level="ERROR"/>-->
<!--<logger name="org.hibernate.boot.internal" level="ERROR"/>-->
<!--<logger name="org.apache.tomcat.util" level="ERROR"/>-->
<logger name="org.springframework.amqp" level="ERROR"/>
<logger name="org.springframework.data.redis" level="ERROR"/>
<logger name="org.springframework.data.jdbc" level="ERROR"/>
<!--<logger name="org.springframework.orm" level="ERROR"/>-->
<!--<logger name="org.springframework.jmx" level="ERROR"/>-->
<!--<logger name="org.springframework.jndi" level="ERROR"/>-->
<!--<logger name="org.springframework.aop" level="ERROR"/>-->
<!--<logger name="org.springframework.web" level="ERROR"/>-->
<!--<logger name="org.springframework.context" level="ERROR"/>-->
<!--<logger name="org.springframework.core" level="ERROR"/>-->
<logger name="org.springframework.beans" level="ERROR"/>
<!--<logger name="org.springframework.boot.web" level="ERROR"/>-->
<!--<logger name="org.springframework.boot.actuate" level="ERROR"/>-->
<!--<logger name="org.springframework.boot.context" level="ERROR"/>-->
<!--<logger name="org.springframework.boot.autoconfigure.logging" level="ERROR"/>-->
<!--<logger name="org.hibernate.type.descriptor.sql.BasicBinder" level="${logging.hibernate.level}"/>-->
<!--<logger name="org.hibernate.engine.QueryParameters" level="DEBUG"/>-->
<!--<logger name="org.hibernate.SQL" level="DEBUG" />-->
<root level="DEBUG">
<appender-ref ref="STDOUT"/>
<appender-ref ref="ROLLINGFILE"/>
</root> </root>
</configuration> </configuration>
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="https://jverification.jiguang.cn/scripts/1.0.0/jverification-web.min.js"></script>
</head>
<body>
</body>
<script>
window.JVerificationInterface.init({
appkey: "1f70875fc3941d8f1964eb63", // 极光官网中创建应用后分配的 appkey,必填
debugMode: true, // 设置是否开启 debug 模式。true 则会打印更多的日志信息。设置 false 则只会输出 w、e 级别的日志。
success: function(data) {
//TODO 初始化成功回调
alert("初始化成功回调");
},
fail: function(data) {
//TODO 初始化失败回调
alert("初始化失败回调");
}
});
</script>
</html>
\ No newline at end of file
import cn.quantgroup.xyqb.security.RSADecrypt;
import cn.quantgroup.xyqb.util.PasswordUtil;
import org.springframework.util.Base64Utils;
/**
* Created by Administrator on 2021/6/25 0025.
*/
public class TestApp {
public static void main(String[] args){
base64();
password();
}
public static void base64(){
String s = new String(Base64Utils.encode(("CM:" +
"WwC-l6t179UtaYPtS02fQeEhh57xXewoUCX7W8N9Izf58Js60yMFSDTq5Oj7nTgg22YjEVSu2WW1m4Q-1tr0u_8Qup886TxKROKb03ujaTt2C69f0DYdRfUEHyLydRsQ3GZEYGINuupf6xJYh493KBmDvpzaDOXSxnZVg0q4jDXrs5g7w-Aucq61JTjHEqCOUcT-4u0YsJIBnYG8QY65RiqZGXd17FmSbWoBM5eKaLr7I2HrdEI2a7p_rimVcqiR4vbq2LQSxTKzOfoIOwDUUhwXKJ0Z_XoAN47tdaRi32qB3jPo_z7UPj71lXpIvtT-6CDzKAh1UKgprxR-LQNpq_ngBSBo-n1KVe9mx-5Ywg0="
+"").getBytes()));
System.out.println(s);
try {
String decrypt = RSADecrypt.decrypt(
"gzDiv4LzHjGoZDfDEgRn5/FKerCD3QmESv4Hh8CPgA6y65wr45/b8ZntRveBXjzriBIoHSXH7UuCkyXq4rHaTceO2St6IRa423TA8SPV0cqw51ZIiNPbMwT4uDSZRVwfy/kKvQrDWIq+5v2a/Xs/1ORYSEqgv2ywBsC1rtoSGvY="
, "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKxDkRtyB5CdWqnFpyCIbxiy7X9A9LSvjtCmiL4YpbxnwVOfbMH5c6e2qbk5egDoIUOPVgAOlCMcYRzlNyBgA9QBFJKSFBK8NnyTrpFe+I9d2I79Iab05LHMhahIjW/98rswBqQvwQE5FBm8ZX1AQcpRAm56xUTymNsSIEQY4+AvAgMBAAECgYA25MEU0d1/Q+VkPEvpnhBo+nucFYLlIRyNeMQSb6BAzX9Zum/Z0Df+tcKX96zdJRuUf9ST6BFkruJzZseOVYpiOlqRNxCwL6TbaL3wA5JqgKcW7vFjLnrKHzUnz+FcWIh6Y3houYHro+ctB1gAaUAkWz1Nvt0dIEJ7NuQmU1ggwQJBAOFK8Bg4GJtzbAKV5X+B6hlp5wzGVQws+nLu40E1NRyIQ4YzK9vUu47oyiADeZSGw0Rp34h3fWXeNZQSBwAgRakCQQDDvlA6Yzf0Rsc+Q3e7iqyuw8gtcpWf+lgnJKInWUHFW+r9MkwHGu/u4Oq4OIkfZF3xXMZ/oVTYZDVJ5H8y924XAkEArYdZ/V2f3oR9ylQIzDiVxvNiSt2s/k7arZJBKqW//fUbBY/+lTl7Ke02WogyqmtOljByQ5u906vfWuizya4R2QJACRqI0K5co9fG3HZ20xoX/ejNHo/9tXsHLordn8be8DbeLvhv4MS38/wx7m9ysSsR02/lK3ptX8MJV25xHAW18QJAeR5WtHzYlx2nm04PYwwlXckEahChAWKm3fPGcm2d3WWYj0HXucyFOh4zdvHCsa77hEYoGCHMS01pG9zUxtHpiQ==");
System.out.println(decrypt);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void password(){
String s = PasswordUtil.MD5WithSalt("111111");
System.out.println(s);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment