This commit is contained in:
MaxKey 2022-04-11 08:42:58 +08:00
parent 6dcd63c8a2
commit 742b660453
12 changed files with 126 additions and 165 deletions

View File

@ -15,7 +15,7 @@
# */ # */
#maxkey properties #maxkey properties
group =maxkey.top group =maxkey.top
version =3.4.0 version =3.5.0
vendor =https://www.maxkey.top vendor =https://www.maxkey.top
author =MaxKeyTop author =MaxKeyTop

View File

@ -44,6 +44,9 @@ public class SocialsAssociate extends JpaBaseEntity {
private String id; private String id;
@Column @Column
private String provider; private String provider;
private String providerName;
private String icon;
@Column @Column
private String userId; private String userId;
@Column @Column
@ -157,6 +160,23 @@ public class SocialsAssociate extends JpaBaseEntity {
this.instId = instId; this.instId = instId;
} }
public String getProviderName() {
return providerName;
}
public void setProviderName(String providerName) {
this.providerName = providerName;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
@Override @Override
public String toString() { public String toString() {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();

View File

@ -1,7 +1,7 @@
#端口号 #端口号
application: application:
name: maxkey-gateway-server name: maxkey-gateway-server
formatted-version: v3.4.0 GA formatted-version: v3.5.0 GA
server: server:
port: 9000 port: 9000
spring: spring:

View File

@ -18,7 +18,7 @@
application.title =MaxKey application.title =MaxKey
#for dynamic service discovery #for dynamic service discovery
spring.application.name =maxkey-monitor spring.application.name =maxkey-monitor
application.formatted-version =v3.4.0 GA application.formatted-version =v3.5.0 GA
#nacos discovery #nacos discovery
spring.cloud.nacos.discovery.enabled =${NACOS_DISCOVERY_ENABLED:false} spring.cloud.nacos.discovery.enabled =${NACOS_DISCOVERY_ENABLED:false}
spring.cloud.nacos.discovery.instance-enabled =false spring.cloud.nacos.discovery.instance-enabled =false

View File

@ -16,9 +16,13 @@
package org.maxkey.persistence.mapper; package org.maxkey.persistence.mapper;
import java.util.List;
import org.apache.mybatis.jpa.persistence.IJpaBaseMapper; import org.apache.mybatis.jpa.persistence.IJpaBaseMapper;
import org.maxkey.entity.SocialsAssociate; import org.maxkey.entity.SocialsAssociate;
import org.maxkey.entity.UserInfo;
public interface SocialsAssociateMapper extends IJpaBaseMapper<SocialsAssociate> { public interface SocialsAssociateMapper extends IJpaBaseMapper<SocialsAssociate> {
public List<SocialsAssociate> queryByUser(UserInfo user);
} }

View File

@ -17,8 +17,11 @@
package org.maxkey.persistence.service; package org.maxkey.persistence.service;
import java.util.List;
import org.apache.mybatis.jpa.persistence.JpaBaseService; import org.apache.mybatis.jpa.persistence.JpaBaseService;
import org.maxkey.entity.SocialsAssociate; import org.maxkey.entity.SocialsAssociate;
import org.maxkey.entity.UserInfo;
import org.maxkey.persistence.mapper.SocialsAssociateMapper; import org.maxkey.persistence.mapper.SocialsAssociateMapper;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@ -39,4 +42,8 @@ public class SocialsAssociatesService extends JpaBaseService<SocialsAssociate>{
} }
public List<SocialsAssociate> queryByUser(UserInfo user) {
return getMapper().queryByUser(user);
}
} }

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.maxkey.persistence.mapper.SocialsAssociateMapper">
<select id="queryByUser" parameterType="UserInfo" resultType="SocialsAssociate">
select
p.provider,
p.providerName,
p.icon,
a.id,
a.userid,
a.username,
a.createdDate,
a.updatedDate
from
mxk_socials_provider p
left join
mxk_socials_associate a
on a.provider = p.provider and a.userid = #{id}
where
a.instid = p.instid
and a.instid = #{instId}
and p.status =1
order by p.sortindex
</select>
</mapper>

View File

@ -146,7 +146,7 @@ public class MaxKeyMvcConfig implements WebMvcConfigurer {
.addPathPatterns("/logs/**") .addPathPatterns("/logs/**")
.addPathPatterns("/userinfo/**") .addPathPatterns("/userinfo/**")
.addPathPatterns("/profile/**") .addPathPatterns("/profile/**")
.addPathPatterns("/safe/**") .addPathPatterns("/config/**")
.addPathPatterns("/historys/**") .addPathPatterns("/historys/**")
.addPathPatterns("/access/session/**") .addPathPatterns("/access/session/**")
.addPathPatterns("/access/session/**/**") .addPathPatterns("/access/session/**/**")

View File

@ -18,26 +18,29 @@
package org.maxkey.web.contorller; package org.maxkey.web.contorller;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.util.UUID; import java.util.Base64;
import java.util.HashMap;
import org.apache.commons.codec.binary.Hex; import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;
import org.maxkey.authn.annotation.CurrentUser;
import org.maxkey.crypto.Base32Utils; import org.maxkey.crypto.Base32Utils;
import org.maxkey.crypto.password.PasswordReciprocal; import org.maxkey.crypto.password.PasswordReciprocal;
import org.maxkey.entity.Message;
import org.maxkey.entity.UserInfo; import org.maxkey.entity.UserInfo;
import org.maxkey.password.onetimepwd.algorithm.OtpKeyUriFormat; import org.maxkey.password.onetimepwd.algorithm.OtpKeyUriFormat;
import org.maxkey.password.onetimepwd.algorithm.OtpSecret; import org.maxkey.password.onetimepwd.algorithm.OtpSecret;
import org.maxkey.persistence.service.UserInfoService; import org.maxkey.persistence.service.UserInfoService;
import org.maxkey.util.RQCodeUtils; import org.maxkey.util.RQCodeUtils;
import org.maxkey.web.WebContext;
import org.maxkey.web.image.ImageEndpoint; import org.maxkey.web.image.ImageEndpoint;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.xkcoding.http.util.StringUtil;
/** /**
@ -46,7 +49,7 @@ import com.xkcoding.http.util.StringUtil;
* *
*/ */
@Controller @Controller
@RequestMapping(value = { "/safe/otp" }) @RequestMapping(value = { "/config" })
public class OneTimePasswordController { public class OneTimePasswordController {
static final Logger _logger = LoggerFactory.getLogger(OneTimePasswordController.class); static final Logger _logger = LoggerFactory.getLogger(OneTimePasswordController.class);
@ -58,115 +61,48 @@ public class OneTimePasswordController {
@Qualifier("otpKeyUriFormat") @Qualifier("otpKeyUriFormat")
OtpKeyUriFormat otpKeyUriFormat; OtpKeyUriFormat otpKeyUriFormat;
@Autowired
@Qualifier("passwordReciprocal")
PasswordReciprocal passwordReciprocal;
@RequestMapping(value = {"/timebased"}) @RequestMapping(value = {"/timebased"})
public ModelAndView timebased() { @ResponseBody
ModelAndView modelAndView = new ModelAndView("safe/timeBased"); public ResponseEntity<?> timebased(@RequestParam String generate,@CurrentUser UserInfo currentUser) {
UserInfo userInfo = WebContext.getUserInfo(); HashMap<String,Object >timebased =new HashMap<String,Object >();
generate(generate,currentUser);
String sharedSecret =
PasswordReciprocal.getInstance().decoder(currentUser.getSharedSecret());
String sharedSecret = userInfo.getId();
if(StringUtil.isNotEmpty(userInfo.getSharedSecret())) {
passwordReciprocal.decoder(userInfo.getSharedSecret());
}
otpKeyUriFormat.setSecret(sharedSecret); otpKeyUriFormat.setSecret(sharedSecret);
String otpauth = otpKeyUriFormat.format(userInfo.getUsername()); String otpauth = otpKeyUriFormat.format(currentUser.getUsername());
byte[] byteSharedSecret = Base32Utils.decode(sharedSecret); byte[] byteSharedSecret = Base32Utils.decode(sharedSecret);
String hexSharedSecret = Hex.encodeHexString(byteSharedSecret); String hexSharedSecret = Hex.encodeHexString(byteSharedSecret);
modelAndView.addObject("id", genRqCode(otpauth));
modelAndView.addObject("userInfo", userInfo); timebased.put("displayName", currentUser.getDisplayName());
modelAndView.addObject("format", otpKeyUriFormat); timebased.put("username", currentUser.getUsername());
modelAndView.addObject("sharedSecret", sharedSecret); timebased.put("digits", otpKeyUriFormat.getDigits());
modelAndView.addObject("hexSharedSecret", hexSharedSecret); timebased.put("period", otpKeyUriFormat.getPeriod());
return modelAndView; timebased.put("sharedSecret", sharedSecret);
timebased.put("hexSharedSecret", hexSharedSecret);
timebased.put("rqCode", genRqCode(otpauth));
return new Message<HashMap<String,Object >>(timebased).buildResponse();
} }
@RequestMapping(value = {"gen/timebased"}) public void generate(String generate,@CurrentUser UserInfo currentUser) {
public ModelAndView gentimebased() { if((StringUtils.isNotBlank(generate)
UserInfo userInfo = WebContext.getUserInfo(); && generate.equalsIgnoreCase("YES"))
||StringUtils.isBlank(currentUser.getSharedSecret())) {
byte[] byteSharedSecret = OtpSecret.generate(otpKeyUriFormat.getCrypto()); byte[] byteSharedSecret = OtpSecret.generate(otpKeyUriFormat.getCrypto());
String sharedSecret = Base32Utils.encode(byteSharedSecret); String sharedSecret = Base32Utils.encode(byteSharedSecret);
sharedSecret = passwordReciprocal.encode(sharedSecret); sharedSecret = PasswordReciprocal.getInstance().encode(sharedSecret);
userInfo.setSharedSecret(sharedSecret); currentUser.setSharedSecret(sharedSecret);
userInfoService.updateSharedSecret(userInfo); userInfoService.updateSharedSecret(currentUser);
WebContext.setUserInfo(userInfo);
return WebContext.redirect("/safe/otp/timebased");
}
@RequestMapping(value = {"/counterbased"})
public ModelAndView counterbased() {
ModelAndView modelAndView = new ModelAndView("safe/counterBased");
UserInfo userInfo = WebContext.getUserInfo();
String sharedSecret = passwordReciprocal.decoder(userInfo.getSharedSecret());
otpKeyUriFormat.setSecret(sharedSecret);
otpKeyUriFormat.setCounter(Long.parseLong(userInfo.getSharedCounter()));
String otpauth = otpKeyUriFormat.format(userInfo.getUsername());
byte[] byteSharedSecret = Base32Utils.decode(sharedSecret);
String hexSharedSecret = Hex.encodeHexString(byteSharedSecret);
modelAndView.addObject("id", genRqCode(otpauth));
modelAndView.addObject("userInfo", userInfo);
modelAndView.addObject("format", otpKeyUriFormat);
modelAndView.addObject("sharedSecret", sharedSecret);
modelAndView.addObject("hexSharedSecret", hexSharedSecret);
return modelAndView;
} }
@RequestMapping(value = {"gen/counterbased"})
public ModelAndView gencounterbased() {
UserInfo userInfo = WebContext.getUserInfo();
byte[] byteSharedSecret = OtpSecret.generate(otpKeyUriFormat.getCrypto());
String sharedSecret = Base32Utils.encode(byteSharedSecret);
sharedSecret = passwordReciprocal.encode(sharedSecret);
userInfo.setSharedSecret(sharedSecret);
userInfo.setSharedCounter("0");
userInfoService.updateSharedSecret(userInfo);
WebContext.setUserInfo(userInfo);
return WebContext.redirect("/safe/otp/counterbased");
} }
@RequestMapping(value = {"/hotp"})
public ModelAndView hotp() {
ModelAndView modelAndView = new ModelAndView("safe/hotp");
UserInfo userInfo = WebContext.getUserInfo();
String sharedSecret = passwordReciprocal.decoder(userInfo.getSharedSecret());
otpKeyUriFormat.setSecret(sharedSecret);
otpKeyUriFormat.setCounter(Long.parseLong(userInfo.getSharedCounter()));
String otpauth = otpKeyUriFormat.format(userInfo.getUsername());
byte[] byteSharedSecret = Base32Utils.decode(sharedSecret);
String hexSharedSecret = Hex.encodeHexString(byteSharedSecret);
modelAndView.addObject("id", genRqCode(otpauth));
modelAndView.addObject("userInfo", userInfo);
modelAndView.addObject("format", otpKeyUriFormat);
modelAndView.addObject("sharedSecret", sharedSecret);
modelAndView.addObject("hexSharedSecret", hexSharedSecret);
return modelAndView;
}
@RequestMapping(value = {"gen/hotp"})
public ModelAndView genhotp() {
UserInfo userInfo = WebContext.getUserInfo();
byte[] byteSharedSecret = OtpSecret.generate(otpKeyUriFormat.getCrypto());
String sharedSecret = Base32Utils.encode(byteSharedSecret);
sharedSecret = passwordReciprocal.encode(sharedSecret);
userInfo.setSharedSecret(sharedSecret);
userInfo.setSharedCounter("0");
userInfoService.updateSharedSecret(userInfo);
WebContext.setUserInfo(userInfo);
return WebContext.redirect("/safe/otp/hotp");
}
public String genRqCode(String otpauth) { public String genRqCode(String otpauth) {
BufferedImage bufferedImage = RQCodeUtils.write2BufferedImage(otpauth, "gif", 300, 300); BufferedImage bufferedImage = RQCodeUtils.write2BufferedImage(otpauth, "gif", 300, 300);
byte[] imageByte = ImageEndpoint.bufferedImage2Byte(bufferedImage); byte[] imageByte = ImageEndpoint.bufferedImage2Byte(bufferedImage);
String uuid = UUID.randomUUID().toString().toLowerCase(); return "data:image/png;base64," + Base64.getEncoder().encodeToString(imageByte);
WebContext.getSession().setAttribute(uuid, imageByte);
return uuid;
} }
} }

View File

@ -17,76 +17,39 @@
package org.maxkey.web.contorller; package org.maxkey.web.contorller;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.maxkey.authn.support.socialsignon.service.SocialSignOnProviderService; import org.maxkey.authn.annotation.CurrentUser;
import org.maxkey.authn.support.socialsignon.service.SocialsAssociateService; import org.maxkey.entity.Message;
import org.maxkey.configuration.ApplicationConfig;
import org.maxkey.entity.Institutions;
import org.maxkey.entity.SocialsAssociate; import org.maxkey.entity.SocialsAssociate;
import org.maxkey.entity.SocialsProvider; import org.maxkey.entity.UserInfo;
import org.maxkey.web.WebConstants; import org.maxkey.persistence.service.SocialsAssociatesService;
import org.maxkey.web.WebContext;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView; import org.springframework.web.bind.annotation.ResponseBody;
@Controller @Controller
@RequestMapping(value={"/socialsignon"}) @RequestMapping(value={"/config/socialsignon"})
public class SocialSignOnListController { public class SocialSignOnListController {
final static Logger _logger = LoggerFactory.getLogger(SocialSignOnListController.class); final static Logger _logger = LoggerFactory.getLogger(SocialSignOnListController.class);
@Autowired @Autowired
SocialSignOnProviderService socialSignOnProviderService; protected SocialsAssociatesService socialsAssociatesService;
@Autowired
protected SocialsAssociateService socialSignOnUserService;
@Autowired @RequestMapping(value={"/fetch"})
@Qualifier("applicationConfig") @ResponseBody
protected ApplicationConfig applicationConfig; public ResponseEntity<?> fetch(@CurrentUser UserInfo currentUser){
@RequestMapping(value = { "/list" }) List<SocialsAssociate> listSocialsAssociate=
public ModelAndView forwardUpdate() { socialsAssociatesService.queryByUser(currentUser);
ModelAndView modelAndView=new ModelAndView("social/socialSignOnProvider"); return new Message<List<SocialsAssociate>>(listSocialsAssociate).buildResponse();
Institutions inst = (Institutions)WebContext.getAttribute(WebConstants.CURRENT_INST);
List<SocialsProvider> listSocialSignOnProvider =
socialSignOnProviderService.loadSocialsProviders(inst.getId()).getSocialSignOnProviders();
SocialsAssociate socialSignOnUser=new SocialsAssociate();
socialSignOnUser.setUserId(WebContext.getUserInfo().getId());
List<SocialsAssociate> listSocialSignOnUserToken= socialSignOnUserService.query(socialSignOnUser);
List<SocialsProvider> listBindSocialSignOnProvider=new ArrayList<SocialsProvider>();
_logger.debug("list SocialSignOnProvider : "+listSocialSignOnProvider);
_logger.debug("list SocialSignOnUserToken : "+listSocialSignOnUserToken);
for (SocialsProvider ssop : listSocialSignOnProvider){
SocialsProvider socialSignOnProvider=new SocialsProvider();
socialSignOnProvider.setProvider(ssop.getProvider());
socialSignOnProvider.setProviderName(ssop.getProviderName());
socialSignOnProvider.setIcon(ssop.getIcon());
socialSignOnProvider.setSortOrder(ssop.getSortOrder());
for(SocialsAssociate ssout :listSocialSignOnUserToken){
if(ssout.getProvider().equals(ssop.getProvider())){
socialSignOnProvider.setUserBind(true);
socialSignOnProvider.setBindTime(ssout.getCreatedDate());
socialSignOnProvider.setLastLoginTime(ssout.getUpdatedDate());
_logger.debug("binded provider : "+ssout.getProvider());
}
}
listBindSocialSignOnProvider.add(socialSignOnProvider);
}
modelAndView.addObject("listSocialSignOnProvider", listBindSocialSignOnProvider);
return modelAndView;
} }
} }

View File

@ -16,7 +16,7 @@
#MaxKey Title and Version # #MaxKey Title and Version #
############################################################################ ############################################################################
application.title =MaxKey application.title =MaxKey
application.formatted-version =v3.4.0 GA application.formatted-version =v3.5.0 GA
#for dynamic service discovery #for dynamic service discovery
spring.application.name =maxkey spring.application.name =maxkey
############################################################################ ############################################################################

View File

@ -16,7 +16,7 @@
#MaxKey Title and Version # #MaxKey Title and Version #
############################################################################ ############################################################################
application.title =MaxKey-Mgt application.title =MaxKey-Mgt
application.formatted-version =v3.4.0 GA application.formatted-version =v3.5.0 GA
#for dynamic service discovery #for dynamic service discovery
spring.application.name =maxkey-mgt spring.application.name =maxkey-mgt
############################################################################ ############################################################################