Browse Source

提交开源任务材料

10.0
LAPTOP-SB56SG4Q\86185 3 years ago
parent
commit
24473deb2b
  1. 5
      README.md
  2. BIN
      lib/CryptoUtil-1.0.2.301.jar
  3. BIN
      lib/bcprov-jdk15on-1.54.jar
  4. BIN
      lib/commons-codec-1.10.jar
  5. BIN
      lib/commons-lang3-3.1.jar
  6. BIN
      lib/commons-logging-1.1.1.jar
  7. BIN
      lib/jdom-2.0.6.jar
  8. BIN
      lib/jdom.jar
  9. BIN
      lib/log4j-1.2.16.jar
  10. BIN
      lib/slf4j-api.jar
  11. BIN
      lib/slf4j-log4j.jar
  12. BIN
      lib/xmlsec-1.5.7.jar
  13. 20
      plugin.xml
  14. 23
      src/main/java/com/fr/plugin/xxxx/saml/CustomLogInOutEventProvider.java
  15. 93
      src/main/java/com/fr/plugin/xxxx/saml/MobileFilter.java
  16. 49
      src/main/java/com/fr/plugin/xxxx/saml/ReportService.java
  17. 70
      src/main/java/com/fr/plugin/xxxx/saml/SignDBAccessProvider.java
  18. 355
      src/main/java/com/fr/plugin/xxxx/saml/SsoFilter.java
  19. 21
      src/main/java/com/fr/plugin/xxxx/saml/dao/RoleUrlDao.java
  20. 23
      src/main/java/com/fr/plugin/xxxx/saml/dao/SignReportDao.java
  21. 21
      src/main/java/com/fr/plugin/xxxx/saml/dao/UserRoleDao.java
  22. 59
      src/main/java/com/fr/plugin/xxxx/saml/entity/RoleUrlEntity.java
  23. 63
      src/main/java/com/fr/plugin/xxxx/saml/entity/SignReportEntity.java
  24. 69
      src/main/java/com/fr/plugin/xxxx/saml/entity/UserRoleEntity.java
  25. 184
      src/main/java/com/fr/plugin/xxxx/saml/schedule/SyncThread.java
  26. 20
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/keystore/KeyInfoException.java
  27. 56
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/keystore/KeystoreInfo.java
  28. 137
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/SAMLAlgorithmUtil.java
  29. 20
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/SAMLException.java
  30. 5
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/SAMLRequest.java
  31. 45
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/SAMLResponse.java
  32. 37
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/SAMLResponseValidator.java
  33. 204
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/SAMLUtil.java
  34. 23
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/ServiceProvider.java
  35. 80
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/assertion/AuthnRequest.java
  36. 1220
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/bean/UserInfoBean.java
  37. 5
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/constant/SsoConstants.java
  38. 19
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/filter/EncodingFilter.java
  39. 131
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/filter/SAMLFilter.java
  40. 18
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/impl/SAMLRequestImpl.java
  41. 262
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/impl/SAMLResponseImpl.java
  42. 180
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/impl/SAMLResponseValidatorImpl.java
  43. 115
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/impl/ServiceProviderImpl.java
  44. 41
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/response/Request.java
  45. 49
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/response/RequestBuilder.java
  46. 27
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/response/UuidGenerator.java
  47. 49
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/servlet/SAMLRequestServlet.java
  48. 132
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/security/AESUtil.java
  49. 148
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/security/AESUtilBak.java
  50. 78
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/security/AesConfigBean.java
  51. 130
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/security/AesGcm.java
  52. 58
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/security/Encrypt.java
  53. 20
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/security/EncryptException.java
  54. 76
      src/main/java/com/fr/plugin/xxxx/saml/xxxx/security/Test.java
  55. 16
      src/main/resources/conf.properties
  56. 31
      src/main/resources/saasclient.properties

5
README.md

@ -1,3 +1,6 @@
# open-JSD-7610
JSD-7610 SAML单点
JSD-7610 SAML单点\
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\
仅作为开发者学习参考使用!禁止用于任何商业用途!\
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。

BIN
lib/CryptoUtil-1.0.2.301.jar

Binary file not shown.

BIN
lib/bcprov-jdk15on-1.54.jar

Binary file not shown.

BIN
lib/commons-codec-1.10.jar

Binary file not shown.

BIN
lib/commons-lang3-3.1.jar

Binary file not shown.

BIN
lib/commons-logging-1.1.1.jar

Binary file not shown.

BIN
lib/jdom-2.0.6.jar

Binary file not shown.

BIN
lib/jdom.jar

Binary file not shown.

BIN
lib/log4j-1.2.16.jar

Binary file not shown.

BIN
lib/slf4j-api.jar

Binary file not shown.

BIN
lib/slf4j-log4j.jar

Binary file not shown.

BIN
lib/xmlsec-1.5.7.jar

Binary file not shown.

20
plugin.xml

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><plugin>
<id>com.fr.plugin.xxxx.saml</id>
<main-package>com.fr.plugin.xxxx.saml</main-package>
<name><![CDATA[saml单点]]></name>
<active>yes</active>
<version>1.63.n</version>
<env-version>10.0</env-version>
<jartime>2018-07-31</jartime>
<vendor>fr.open</vendor>
<description><![CDATA[荣耀saml单点]]></description>
<change-notes><![CDATA[
<!--[2019-01-09]初始化插件。<br/>
[2018-07-31]初始化插件。<br/>-->
]]></change-notes>
<extra-decision>
<GlobalRequestFilterProvider class="com.fr.plugin.xxxx.saml.SsoFilter"/>
<LogInOutEventProvider class="com.fr.plugin.xxxx.saml.CustomLogInOutEventProvider"/>
</extra-decision>
<function-recorder class="com.fr.plugin.xxxx.saml.SsoFilter"/>
</plugin>

23
src/main/java/com/fr/plugin/xxxx/saml/CustomLogInOutEventProvider.java

@ -0,0 +1,23 @@
package com.fr.plugin.xxxx.saml;
import com.fr.decision.fun.impl.AbstractLogInOutEventProvider;
import com.fr.decision.webservice.login.LogInOutResultInfo;
import com.fr.general.PropertiesUtils;
import com.fr.plugin.xxxx.saml.xxxx.saml.constant.SsoConstants;
import javax.servlet.http.HttpSession;
/**
* @Author fr.open
* @Date 2020/9/18
* @Description
**/
public class CustomLogInOutEventProvider extends AbstractLogInOutEventProvider {
@Override
public String logoutAction(LogInOutResultInfo result) {
HttpSession session = result.getRequest().getSession();
session.removeAttribute(SsoConstants.SESSION_USER_INFO_KEY);
session.invalidate();
return PropertiesUtils.getProperties("conf").getProperty("logout");
}
}

93
src/main/java/com/fr/plugin/xxxx/saml/MobileFilter.java

@ -0,0 +1,93 @@
package com.fr.plugin.xxxx.saml;
import com.fr.decision.authority.data.User;
import com.fr.decision.webservice.exception.user.UserNotExistException;
import com.fr.decision.webservice.utils.DecisionServiceConstants;
import com.fr.decision.webservice.v10.login.LoginService;
import com.fr.decision.webservice.v10.user.UserService;
import com.fr.general.PropertiesUtils;
import com.fr.log.FineLoggerFactory;
import com.fr.third.springframework.util.DigestUtils;
import com.fr.web.utils.WebUtils;
import org.apache.commons.lang3.StringUtils;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
/**
* @Author fr.open
* @Date 2020/9/10
* @Description
**/
public class MobileFilter {
private String key;
private int timeout = 5;
public MobileFilter() {
key = PropertiesUtils.getProperties("conf").getProperty("key");
FineLoggerFactory.getLogger().info("get key config is {}", key);
String time = PropertiesUtils.getProperties("conf").getProperty("timeout");
FineLoggerFactory.getLogger().info("get timeout config is {}", time);
if (StringUtils.isNumeric(time)) {
timeout = Integer.parseInt(time);
}
}
public boolean doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) {
String sign = WebUtils.getHTTPRequestParameter(req, "sign");
String uid = WebUtils.getHTTPRequestParameter(req, "uid");
String time = WebUtils.getHTTPRequestParameter(req, "time");
if (StringUtils.isBlank(sign) || StringUtils.isBlank(uid) || StringUtils.isBlank(time)) {
return false;
}
try {
String encode = DigestUtils.md5DigestAsHex(String.format("%s_%s_%s", uid, time, key).getBytes("UTF-8"));
if (encode.equalsIgnoreCase(sign) && Instant.now().isBefore(Instant.ofEpochMilli(Long.valueOf(time)).plus(timeout, ChronoUnit.MINUTES))) {
//uid = uid.length() > 8 ? uid.substring(uid.length() - 8) : uid;
if (!loginFromToken(req, res, uid)) {
res.sendRedirect(req.getContextPath() + "/mobileTip.html");
} else {
filterChain.doFilter(req, res);
}
return true;
} else {
res.sendRedirect(req.getContextPath() + "/mobileTip.html");
return true;
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return false;
}
private boolean loginFromToken(HttpServletRequest req, HttpServletResponse res, String username) {
try {
if (StringUtils.isNotEmpty(username)) {
FineLoggerFactory.getLogger().info("current username:" + username);
User user = UserService.getInstance().getUserByUserName(username);
FineLoggerFactory.getLogger().info("get user:" + user);
if (user == null) {
throw new UserNotExistException();
}
String token = LoginService.getInstance().login(req, res, username);
FineLoggerFactory.getLogger().info("get login token:" + token);
req.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME, token);
FineLoggerFactory.getLogger().info("username:" + username + "login success");
return true;
} else {
FineLoggerFactory.getLogger().warn("username is null!");
return false;
}
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return false;
}
}

49
src/main/java/com/fr/plugin/xxxx/saml/ReportService.java

@ -0,0 +1,49 @@
package com.fr.plugin.xxxx.saml;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.xxxx.saml.dao.SignReportDao;
import com.fr.plugin.xxxx.saml.entity.SignReportEntity;
import com.fr.stable.db.action.DBAction;
import com.fr.stable.db.dao.DAOContext;
import com.fr.stable.query.QueryFactory;
import com.fr.stable.query.restriction.RestrictionFactory;
import java.util.List;
/**
* @Author fr.open
* @Date 2020/12/3
* @Description
**/
public class ReportService {
private ReportService() {
}
public static ReportService getInstance() {
return new ReportService();
}
public boolean isAuth(String report) {
List<SignReportEntity> query = null;
try {
return SignDBAccessProvider.getDbAccessor().runDMLAction(new DBAction<Boolean>() {
@Override
public Boolean run(DAOContext daoContext) throws Exception {
List<SignReportEntity> list = daoContext.getDAO(SignReportDao.class).find(QueryFactory.create().addRestriction(RestrictionFactory.eq("signFlag",true)));
for (SignReportEntity entity : list) {
if (report.contains(entity.getReport())) {
return false;
}
}
return true;
}
});
} catch (Exception e) {
FineLoggerFactory.getLogger().info(e.getMessage(), e);
}
return true;
}
}

70
src/main/java/com/fr/plugin/xxxx/saml/SignDBAccessProvider.java

@ -0,0 +1,70 @@
package com.fr.plugin.xxxx.saml;
import com.fr.db.fun.impl.AbstractDBAccessProvider;
import com.fr.plugin.xxxx.saml.dao.RoleUrlDao;
import com.fr.plugin.xxxx.saml.dao.SignReportDao;
import com.fr.plugin.xxxx.saml.dao.UserRoleDao;
import com.fr.plugin.xxxx.saml.entity.RoleUrlEntity;
import com.fr.plugin.xxxx.saml.entity.SignReportEntity;
import com.fr.plugin.xxxx.saml.entity.UserRoleEntity;
import com.fr.stable.db.accessor.DBAccessor;
import com.fr.stable.db.dao.BaseDAO;
import com.fr.stable.db.dao.DAOProvider;
/**
* @Author fr.open
* @Date 2020/12/3
* @Description
**/
public class SignDBAccessProvider extends AbstractDBAccessProvider {
private static DBAccessor dbAccessor = null;
public static DBAccessor getDbAccessor() {
return dbAccessor;
}
@Override
public DAOProvider[] registerDAO() {
return new DAOProvider[]{
new DAOProvider() {
@Override
public Class getEntityClass() {
return SignReportEntity.class;
}
@Override
public Class<? extends BaseDAO> getDAOClass() {
return SignReportDao.class;
}
},
new DAOProvider() {
@Override
public Class getEntityClass() {
return UserRoleEntity.class;
}
@Override
public Class<? extends BaseDAO> getDAOClass() {
return UserRoleDao.class;
}
},
new DAOProvider() {
@Override
public Class getEntityClass() {
return RoleUrlEntity.class;
}
@Override
public Class<? extends BaseDAO> getDAOClass() {
return RoleUrlDao.class;
}
}
};
}
@Override
public void onDBAvailable(DBAccessor dbAccessor) {
SignDBAccessProvider.dbAccessor = dbAccessor;
}
}

355
src/main/java/com/fr/plugin/xxxx/saml/SsoFilter.java

@ -0,0 +1,355 @@
package com.fr.plugin.xxxx.saml;
import com.fr.base.TemplateUtils;
import com.fr.data.NetworkHelper;
import com.fr.decision.authority.data.User;
import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider;
import com.fr.decision.mobile.terminal.TerminalHandler;
import com.fr.decision.webservice.bean.authentication.OriginUrlResponseBean;
import com.fr.decision.webservice.exception.user.UserNotExistException;
import com.fr.decision.webservice.utils.DecisionServiceConstants;
import com.fr.decision.webservice.utils.DecisionStatusService;
import com.fr.decision.webservice.utils.WebServiceUtils;
import com.fr.decision.webservice.v10.login.LoginService;
import com.fr.decision.webservice.v10.login.TokenResource;
import com.fr.decision.webservice.v10.user.UserService;
import com.fr.general.PropertiesUtils;
import com.fr.locale.InterProviderFactory;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.xxxx.saml.xxxx.saml.SAMLException;
import com.fr.plugin.xxxx.saml.xxxx.saml.SAMLResponseValidator;
import com.fr.plugin.xxxx.saml.xxxx.saml.constant.SsoConstants;
import com.fr.plugin.xxxx.saml.xxxx.saml.impl.SAMLRequestImpl;
import com.fr.plugin.xxxx.saml.xxxx.saml.impl.SAMLResponseValidatorImpl;
import com.fr.plugin.xxxx.saml.schedule.SyncThread;
import com.fr.plugin.transform.FunctionRecorder;
import com.fr.scheduler.QuartzContext;
import com.fr.scheduler.ScheduleJobManager;
import com.fr.stable.StringUtils;
import com.fr.stable.web.Device;
import com.fr.third.v2.org.quartz.CronScheduleBuilder;
import com.fr.third.v2.org.quartz.JobKey;
import com.fr.third.v2.org.quartz.SchedulerException;
import com.fr.third.v2.org.quartz.TriggerBuilder;
import com.fr.web.utils.WebUtils;
import com.fr.third.org.apache.commons.codec.binary.Base64;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* @Author fr.open
* @Date 2020/9/10
* @Description
**/
@FunctionRecorder
public class SsoFilter extends AbstractGlobalRequestFilterProvider {
private static String[] notFilter = {
"/decision/file", "/decision/resources",
"/decision/login/config", "/decision/system/info", "/decision/login/slider",
"/decision/remote", "/share", "/mobileTip.html", "/link"
};
@Override
public String filterName() {
return "honor";
}
@Override
public String[] urlPatterns() {
initSchedule();
return new String[]{"/*"};
}
@Override
public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) {
if (isLogin(req) || isResource(req)) {
filter(req, res, filterChain);
return;
}
String samlResp = req.getParameter("SAMLResponse");
String viewlet = WebUtils.getHTTPRequestParameter(req, "viewlet");
String reportlet = WebUtils.getHTTPRequestParameter(req, "reportlet");
String formlet = WebUtils.getHTTPRequestParameter(req, "formlet");
String let = StringUtils.isNotBlank(viewlet) ? viewlet : StringUtils.isNotBlank(reportlet) ? reportlet : formlet;
//在判断是否是需授权报表
if (StringUtils.isBlank(samlResp) && StringUtils.isNotBlank(let) && !ReportService.getInstance().isAuth(let)) {
filter(req, res, filterChain);
return;
}
if (isMobileDevice(req) && new MobileFilter().doFilter(req, res, filterChain)) {
return;
}
HttpSession session = req.getSession(true);
if (session == null || session.getAttribute(SsoConstants.SESSION_USER_INFO_KEY) == null) {
FineLoggerFactory.getLogger().info("samlResp is {}", samlResp);
if (samlResp != null && !samlResp.equals("")) {
try {
byte[] buffer = new Base64().decode(samlResp.getBytes(req.getCharacterEncoding() == null ? "UTF-8" : req.getCharacterEncoding()));
FineLoggerFactory.getLogger().info("decode base64 result is {}", new String(buffer, StandardCharsets.UTF_8));
SAMLResponseValidator vld = new SAMLResponseValidatorImpl(
new String(buffer, StandardCharsets.UTF_8));
vld.validate();
//UserInfoBean uiBean = vld.getUIBean();
FineLoggerFactory.getLogger().info("decode user bean is [{}]", vld.getUid());
loginFromToken(req, res, vld.getUid());
FineLoggerFactory.getLogger().info("login bean set session!");
session.setAttribute(SsoConstants.SESSION_USER_INFO_KEY, vld.getUid());
String prefix = TemplateUtils.render("${fineServletURL}");
if (isMobileDevice(req) && (req.getRequestURI().endsWith(prefix + "/") || req.getRequestURI().endsWith(prefix))) {
String url = req.getRequestURL().toString().endsWith("/") ? req.getRequestURL().toString() + "url/mobile" : req.getRequestURL().toString() + "/url/mobile";
FineLoggerFactory.getLogger().info("forward {} to {}", req.getRequestURI(), url);
String jump = getOrigin(req);
FineLoggerFactory.getLogger().info("get Origin path is {}", jump);
if (StringUtils.isNotBlank(jump)) {
res.sendRedirect(jump);
} else {
res.sendRedirect(url);
}
return;
}
String jump = getOrigin(req);
FineLoggerFactory.getLogger().info("get Origin path is {}", jump);
if (StringUtils.isNotBlank(jump)) {
res.sendRedirect(jump);
return;
}
filter(req, res, filterChain);
return;
} catch (SAMLException | UnsupportedEncodingException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
req.setAttribute("SAMLRequest", e.getMessage());
setResError(res, e);
} catch (UserNotExistException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
setResError(res, e);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
} else {
try {
FineLoggerFactory.getLogger().info("samlResp is null,redirect login!");
/*byte[] samlRequest = new SAMLRequestImpl().generate().getBytes(StandardCharsets.UTF_8);
samlRequest = new Base64().encode(samlRequest);
req.setAttribute("SAMLRequest", new String(samlRequest, StandardCharsets.UTF_8));
FineLoggerFactory.getLogger().info("return page is:{}",PropertiesUtils.getProperties("conf").getProperty("return"));
req.getRequestDispatcher(PropertiesUtils.getProperties("conf").getProperty("return")).forward(req, res);*/
byte[] samlRequest = new SAMLRequestImpl().generate().getBytes(StandardCharsets.UTF_8);
String saml = new String(new Base64().encode(samlRequest), StandardCharsets.UTF_8.name());
String url = PropertiesUtils.getProperties("conf").getProperty("return");
String back = String.format("%s?SAMLRequest=%s&RelayState=null", url, URLEncoder.encode(saml, StandardCharsets.UTF_8.toString()));
FineLoggerFactory.getLogger().info("back login :{}", back);
String jump = req.getRequestURL() + (req.getQueryString() == null ? StringUtils.EMPTY : "?" + req.getQueryString());
String id = UUID.randomUUID().toString();
DecisionStatusService.originUrlStatusService().put(id, new OriginUrlResponseBean(jump));//添加重定向地址
Cookie cookie = new Cookie("ORIGIN_URL", id);
cookie.setPath("/");
cookie.setHttpOnly(true);
res.addCookie(cookie);
res.sendRedirect(back);
return;
} catch (SAMLException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
req.setAttribute("SAMLRequest", e.getMessage());
setResError(res, e);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}
String id = (String) session.getAttribute(SsoConstants.SESSION_USER_INFO_KEY);
if (StringUtils.isNotBlank(id)) {
FineLoggerFactory.getLogger().info("get user:{} form session", id);
loginFromToken(req, res, id);
filter(req, res, filterChain);
}
return;
}
private void setError(HttpServletResponse res) {
try {
PrintWriter printWriter = WebUtils.createPrintWriter(res);
Map<String, Object> map = new HashMap<>();
map.put("result", InterProviderFactory.getProvider().getLocText("Fine-Engine_Error_Page_Result"));
map.put("reason", "权限生效时间为2小时,如有疑问,请联系运维人员");
map.put("solution", InterProviderFactory.getProvider().getLocText("Fine-Engine_Please_Contact_Platform_Admin"));
String page = WebServiceUtils.parseWebPageResourceSafe("com/fr/web/controller/decision/entrance/resources/unavailable.html", map);
printWriter.write(page);
printWriter.flush();
printWriter.close();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
private String getViewlet(HttpServletRequest req) {
return WebUtils.getHTTPRequestParameter(req, "viewlet") == null ?
WebUtils.getHTTPRequestParameter(req, "formlet")
: WebUtils.getHTTPRequestParameter(req, "viewlet");
}
private String getOrigin(HttpServletRequest req) throws Exception {
Cookie[] cookies = req.getCookies();
if (cookies == null) {
return null;
}
for (int i = 0; i < cookies.length; i++) {
if ("ORIGIN_URL".equals(cookies[i].getName())) {
String id = cookies[i].getValue();
OriginUrlResponseBean path = DecisionStatusService.originUrlStatusService().get(id);
return path == null ? StringUtils.EMPTY : path.getOriginUrl();
}
}
return StringUtils.EMPTY;
}
private boolean isResource(HttpServletRequest req) {
String viewlet = WebUtils.getHTTPRequestParameter(req, "viewlet");
String reportlet = WebUtils.getHTTPRequestParameter(req, "reportlet");
String formlet = WebUtils.getHTTPRequestParameter(req, "formlet");
String let = StringUtils.isNotBlank(viewlet) ? viewlet : StringUtils.isNotBlank(reportlet) ? reportlet : formlet;
String op = WebUtils.getHTTPRequestParameter(req, "op");
if (StringUtils.isNotBlank(op) && StringUtils.isBlank(let)) {
return true;
}
if (req.getRequestURI().endsWith("js") || req.getRequestURI().endsWith("css")) {
return true;
}
for (int i = 0; i < notFilter.length; i++) {
if (req.getRequestURI().contains(notFilter[i])) {
return true;
}
}
return false;
}
private void setResError(HttpServletResponse res, Exception e) {
try {
WebUtils.printAsString(res, e.getMessage());
} catch (Exception exception) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
private boolean loginFromToken(HttpServletRequest req, HttpServletResponse res, String username) {
try {
if (StringUtils.isNotEmpty(username)) {
FineLoggerFactory.getLogger().info("current username:" + username);
User user = UserService.getInstance().getUserByUserName(username);
FineLoggerFactory.getLogger().info("get user:" + user);
if (user == null) {
throw new UserNotExistException();
}
String token = LoginService.getInstance().login(req, res, username);
FineLoggerFactory.getLogger().info("get login token:" + token);
req.setAttribute(DecisionServiceConstants.FINE_AUTH_TOKEN_NAME, token);
FineLoggerFactory.getLogger().info("username:" + username + "login success");
return true;
} else {
FineLoggerFactory.getLogger().warn("username is null!");
return false;
}
} catch (UserNotExistException e) {
throw new UserNotExistException();
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
return false;
}
private void filter(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) {
try {
filterChain.doFilter(req, res);
} catch (IOException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
} catch (ServletException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
private boolean isLogin(HttpServletRequest request) {
String oldToken = TokenResource.COOKIE.getToken(request);
return oldToken != null && checkTokenValid(request, (String) oldToken);
}
private boolean checkTokenValid(HttpServletRequest req, String token) {
try {
Device device = NetworkHelper.getDevice(req);
LoginService.getInstance().loginStatusValid(token, TerminalHandler.getTerminal(req, device));
return true;
} catch (Exception ignore) {
}
return false;
}
public boolean isMobileDevice(HttpServletRequest request) {
String deviceType = WebUtils.getHTTPRequestParameter(request,"deviceType");
if(StringUtils.isNotBlank(deviceType)){
FineLoggerFactory.getLogger().info("get deviceType is {}",deviceType);
return StringUtils.equals(deviceType,"mobile");
}
String requestHeader = request.getHeader("user-agent");
String[] deviceArray = new String[]{"android", "iphone", "ios", "windows phone"};
if (requestHeader == null) {
return false;
}
requestHeader = requestHeader.toLowerCase();
for (int i = 0; i < deviceArray.length; i++) {
if (requestHeader.contains(deviceArray[i])) {
FineLoggerFactory.getLogger().info("current request:{} is mobile request!", request.getRequestURI());
return true;
}
}
return false;
}
public static void initSchedule() {
JobKey jobKey = new JobKey("syncRole", "syncGroup");
try {
if (QuartzContext.getInstance().getScheduler().checkExists(jobKey)) {
ScheduleJobManager.getInstance().removeJob(jobKey.getName(), jobKey.getGroup());
}
} catch (SchedulerException e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
addSchedule(jobKey);
}
private static void addSchedule(JobKey jobKey) {
Map<String, Object> param = new HashMap();
TriggerBuilder triggerBuilder = TriggerBuilder.newTrigger();
triggerBuilder.forJob(jobKey.getName(), jobKey.getGroup()).withIdentity(jobKey.getName(), jobKey.getGroup()).startNow();
String cron = com.fr.base.PropertiesUtils.getProperties("conf").getProperty("cron");
if (StringUtils.isBlank(cron)) {
FineLoggerFactory.getLogger().error("cron is null schedule start failed");
return;
}
CronScheduleBuilder schedule = CronScheduleBuilder.cronSchedule(cron);
triggerBuilder.withSchedule(schedule);
try {
ScheduleJobManager.getInstance().addJob(jobKey.getName(), jobKey.getGroup(), "sync job", SyncThread.class, triggerBuilder.build(), param);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
}

21
src/main/java/com/fr/plugin/xxxx/saml/dao/RoleUrlDao.java

@ -0,0 +1,21 @@
package com.fr.plugin.xxxx.saml.dao;
import com.fr.plugin.xxxx.saml.entity.RoleUrlEntity;
import com.fr.stable.db.dao.BaseDAO;
import com.fr.stable.db.session.DAOSession;
/**
* @Author fr.open
* @Date 2021/5/13
* @Description
**/
public class RoleUrlDao extends BaseDAO<RoleUrlEntity> {
public RoleUrlDao(DAOSession daoSession) {
super(daoSession);
}
@Override
protected Class<RoleUrlEntity> getEntityClass() {
return RoleUrlEntity.class;
}
}

23
src/main/java/com/fr/plugin/xxxx/saml/dao/SignReportDao.java

@ -0,0 +1,23 @@
package com.fr.plugin.xxxx.saml.dao;
import com.fr.plugin.xxxx.saml.entity.SignReportEntity;
import com.fr.stable.db.dao.BaseDAO;
import com.fr.stable.db.session.DAOSession;
/**
* @Author fr.open
* @Date 2020/12/3
* @Description
**/
public class SignReportDao extends BaseDAO<SignReportEntity> {
public SignReportDao(DAOSession daoSession) {
super(daoSession);
}
@Override
protected Class<SignReportEntity> getEntityClass() {
return SignReportEntity.class;
}
}

21
src/main/java/com/fr/plugin/xxxx/saml/dao/UserRoleDao.java

@ -0,0 +1,21 @@
package com.fr.plugin.xxxx.saml.dao;
import com.fr.plugin.xxxx.saml.entity.UserRoleEntity;
import com.fr.stable.db.dao.BaseDAO;
import com.fr.stable.db.session.DAOSession;
/**
* @Author fr.open
* @Date 2021/5/13
* @Description
**/
public class UserRoleDao extends BaseDAO<UserRoleEntity> {
public UserRoleDao(DAOSession daoSession) {
super(daoSession);
}
@Override
protected Class<UserRoleEntity> getEntityClass() {
return UserRoleEntity.class;
}
}

59
src/main/java/com/fr/plugin/xxxx/saml/entity/RoleUrlEntity.java

@ -0,0 +1,59 @@
package com.fr.plugin.xxxx.saml.entity;
import com.fr.stable.db.entity.BaseEntity;
import com.fr.third.javax.persistence.Column;
import com.fr.third.javax.persistence.Entity;
import com.fr.third.javax.persistence.Table;
/**
* @Author fr.open
* @Date 2021/5/13
* @Description
**/
@Entity
@Table(name = "fine_role_url_wp")
public class RoleUrlEntity extends BaseEntity {
private static final long serialVersionUID = -6715601520739733691L;
@Column(name = "url", length = 200)
private String url;
@Column(name = "roleId", length = 200)
private String roleId;
@Column(name = "roleName_EN", length = 200)
private String roleName_EN;
@Column(name = "roleName_CN", length = 200)
private String roleName_CN;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getRoleId() {
return roleId;
}
public void setRoleId(String roleId) {
this.roleId = roleId;
}
public String getRoleName_EN() {
return roleName_EN;
}
public void setRoleName_EN(String roleName_EN) {
this.roleName_EN = roleName_EN;
}
public String getRoleName_CN() {
return roleName_CN;
}
public void setRoleName_CN(String roleName_CN) {
this.roleName_CN = roleName_CN;
}
}

63
src/main/java/com/fr/plugin/xxxx/saml/entity/SignReportEntity.java

@ -0,0 +1,63 @@
package com.fr.plugin.xxxx.saml.entity;
import com.fr.stable.db.entity.BaseEntity;
import com.fr.third.javax.persistence.Column;
import com.fr.third.javax.persistence.Entity;
import com.fr.third.javax.persistence.Table;
import java.util.Date;
/**
* @Author fr.open
* @Date 2020/12/3
* @Description
**/
@Entity
@Table(name = "plugin_sign_report")
public class SignReportEntity extends BaseEntity {
@Column(name = "user_id")
String userId;
@Column(name = "update_time")
Date updateTime;
@Column(name = "sign_flag")
boolean signFlag;
@Column(name = "report")
String report;
public SignReportEntity() {
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public Date getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Date updateTime) {
this.updateTime = updateTime;
}
public boolean isSignFlag() {
return signFlag;
}
public void setSignFlag(boolean signFlag) {
this.signFlag = signFlag;
}
public String getReport() {
return report;
}
public void setReport(String report) {
this.report = report;
}
}

69
src/main/java/com/fr/plugin/xxxx/saml/entity/UserRoleEntity.java

@ -0,0 +1,69 @@
package com.fr.plugin.xxxx.saml.entity;
import com.fr.stable.db.entity.BaseEntity;
import com.fr.third.javax.persistence.Column;
import com.fr.third.javax.persistence.Entity;
import com.fr.third.javax.persistence.Table;
/**
* @Author fr.open
* @Date 2021/5/13
* @Description
**/
@Entity
@Table(name = "fine_user_role_wp")
public class UserRoleEntity extends BaseEntity {
private static final long serialVersionUID = 3637766371586218549L;
@Column(name = "userAccount", length = 50)
private String userAccount;
@Column(name = "userName", length = 50)
private String userName;
@Column(name = "roleId", length = 50)
private String roleId;
@Column(name = "roleName_EN", length = 50)
private String roleName_EN;
@Column(name = "roleName_CN", length = 50)
private String roleName_CN;
public String getUserAccount() {
return userAccount;
}
public void setUserAccount(String userAccount) {
this.userAccount = userAccount;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getRoleId() {
return roleId;
}
public void setRoleId(String roleId) {
this.roleId = roleId;
}
public String getRoleName_EN() {
return roleName_EN;
}
public void setRoleName_EN(String roleName_EN) {
this.roleName_EN = roleName_EN;
}
public String getRoleName_CN() {
return roleName_CN;
}
public void setRoleName_CN(String roleName_CN) {
this.roleName_CN = roleName_CN;
}
}

184
src/main/java/com/fr/plugin/xxxx/saml/schedule/SyncThread.java

@ -0,0 +1,184 @@
package com.fr.plugin.xxxx.saml.schedule;
import com.fr.cluster.core.ClusterNode;
import com.fr.data.impl.DBTableData;
import com.fr.data.impl.MemCachedDBDataModel;
import com.fr.data.impl.NameDatabaseConnection;
import com.fr.decision.authority.AuthorityContext;
import com.fr.decision.authority.data.CustomRole;
import com.fr.decision.authority.data.User;
import com.fr.decision.webservice.annotation.RoleCheckerType;
import com.fr.decision.webservice.bean.authority.PrivilegeBean;
import com.fr.decision.webservice.v10.authority.AuthorityService;
import com.fr.decision.webservice.v10.user.UserService;
import com.fr.general.PropertiesUtils;
import com.fr.json.JSONObject;
import com.fr.log.FineLoggerFactory;
import com.fr.plugin.xxxx.saml.entity.RoleUrlEntity;
import com.fr.scheduler.job.FineScheduleJob;
import com.fr.stable.StringUtils;
import com.fr.stable.query.QueryFactory;
import com.fr.stable.query.restriction.RestrictionFactory;
import com.fr.third.guava.collect.Sets;
import com.fr.third.v2.org.quartz.JobExecutionContext;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Author fr.open
* @Date 2021/5/31
* @Description
**/
public class SyncThread extends FineScheduleJob {
private static final String carrierType = "role";
private static final String externalType = "template";
private static final JSONObject bean = new JSONObject("{\"id\":\"reportlets\",\"values\":[{\"privilegeType\":102,\"privilegeValue\":1},{\"privilegeType\":103,\"privilegeValue\":1}]}");
private static final JSONObject tempBean = new JSONObject("{\"id\":\"\",\"values\":[{\"privilegeType\":102,\"privilegeValue\":2},{\"privilegeType\":103,\"privilegeValue\":2}]}");
@Override
public void run(JobExecutionContext jobExecutionContext, ClusterNode clusterNode) throws Exception {
User user = UserService.getInstance().getUserByUserName(PropertiesUtils.getProperties("conf").getProperty("admin"));
if (user == null) {
FineLoggerFactory.getLogger().error("super user is null!");
return;
}
Map<String, String> roles = getRoles();
Map<String, List<RoleUrlEntity>> delete = getRoleList(-1);
FineLoggerFactory.getLogger().info("start sync delete auth");
Iterator<String> iterator = delete.keySet().iterator();
List<RoleUrlEntity> updateIds = new ArrayList<>();
while (iterator.hasNext()) {
String key = iterator.next();
List<RoleUrlEntity> list = delete.get(key);
if (StringUtils.isBlank(roles.get(key)) || delete.get(key) == null || delete.get(key).isEmpty()) {
continue;
}
//先删除权限
for (RoleUrlEntity temp : list) {
try {
String viewlet = temp.getUrl();
PrivilegeBean privilegeBean = bean.mapTo(PrivilegeBean.class);
privilegeBean.setId(viewlet);
FineLoggerFactory.getLogger().info("remove temp:{} by role",viewlet,temp);
auth(user, roles.get(key), privilegeBean);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
updateIds.addAll(list);
}
updateStatus(updateIds.stream().map(e->e.getId()).collect(Collectors.toList()));
FineLoggerFactory.getLogger().info("sync finish delete size is {}",updateIds.size());
FineLoggerFactory.getLogger().info("start sync add auth");
Map<String, List<RoleUrlEntity>> add = getRoleList(0);
Iterator<String> it = add.keySet().iterator();
List<RoleUrlEntity> addIds = new ArrayList();
while (it.hasNext()) {
String key = it.next();
List<RoleUrlEntity> list = add.get(key);
if (StringUtils.isBlank(roles.get(key)) || add.get(key) == null || add.get(key).isEmpty()) {
continue;
}
//先删除权限
for (RoleUrlEntity temp : list) {
try {
String viewlet = temp.getUrl();
PrivilegeBean privilegeBean = tempBean.mapTo(PrivilegeBean.class);
privilegeBean.setId(viewlet);
auth(user, roles.get(key), privilegeBean);
FineLoggerFactory.getLogger().info("add temp:{} to role",viewlet,temp);
} catch (Exception e) {
FineLoggerFactory.getLogger().error(e.getMessage(), e);
}
}
addIds.addAll(list);
}
updateStatus(addIds.stream().map(e->e.getId()).collect(Collectors.toList()));
FineLoggerFactory.getLogger().info("sync finish add size is {}",addIds.size());
/*Map<String, String> roles = getRoles();
//removeAuth(new ArrayList(roles.values()));
Map<String, List<String>> roleList = getRoleList();
addAuth(roleList, roles);*/
}
public void test(){
try {
CustomRole customRoles = AuthorityContext.getInstance().getCustomRoleController().findOne(QueryFactory.create().addRestriction(RestrictionFactory.eq("name", "test1")));
User user = UserService.getInstance().getUserByUserName("1");
PrivilegeBean privilegeBean = tempBean.mapTo(PrivilegeBean.class);
privilegeBean.setId("reportlets");
auth(user, customRoles.getId(), privilegeBean);
} catch (Exception e) {
e.printStackTrace();
}
}
private Map<String, List<RoleUrlEntity>> getRoleList(Integer status) throws Exception {
String sql = "select roleName_CN,id,url_wp from fine_role_url_wp where status = " + status;
FineLoggerFactory.getLogger().info("query sql is [{}]",sql);
String connection = PropertiesUtils.getProperties("conf").getProperty("connection");
FineLoggerFactory.getLogger().info("query connection is {}",connection);
MemCachedDBDataModel dbDataModel = (MemCachedDBDataModel) DBTableData
.createCacheableDBResultSet(new NameDatabaseConnection(connection),sql , -1);
int rowCount = dbDataModel.getRowCount();
Map<String, List<RoleUrlEntity>> map = new HashMap();
for (int i = 0; i < rowCount; i++) {
List<RoleUrlEntity> roles = map.get(dbDataModel.getValueAt(i, 0).toString());
if (roles == null) {
roles = new ArrayList<>();
}
RoleUrlEntity entity = new RoleUrlEntity();
entity.setId(dbDataModel.getValueAt(i, 1).toString());
entity.setUrl(dbDataModel.getValueAt(i, 2).toString());
roles.add(entity);
map.put(dbDataModel.getValueAt(i, 0).toString(), roles);
}
return map;
}
private void updateStatus(List<String> id) {
String sql = "update fine_role_url_wp set status = 1 where id in ('" + id.stream().collect(Collectors.joining("','")) + "')";
FineLoggerFactory.getLogger().info("update sql is [{}]",sql);
MemCachedDBDataModel dbDataModel = (MemCachedDBDataModel) DBTableData
.createCacheableDBResultSet(new NameDatabaseConnection(PropertiesUtils.getProperties("conf").getProperty("connection")), sql, -1);
}
private String getViewlet(String temp) throws UnsupportedEncodingException {
String params = temp.substring(temp.indexOf("?") + 1);
for (int i = 0; i < params.split("&").length; i++) {
String param = params.split("&")[i];
if (param.split("=")[0].equals("viewlet")) {
return URLDecoder.decode(URLDecoder.decode(param.split("=")[1], "UTF-8"), "UTF-8");
}
}
return StringUtils.EMPTY;
}
private void auth(User user, String role, PrivilegeBean privilegeBean) throws Exception {
RoleCheckerType.checkAuthority(user.getId(), role, carrierType);
AuthorityService.getInstance().checkUserAssignAuthority(user.getId(), Sets.newHashSet(new String[]{privilegeBean.getId()}), privilegeBean.getAuthorityTypes(), externalType);
//Reflect.on("com.fr.decision.webservice.v10.authority.AuthorityService").call("updateAuthorityEntityByCarrier",user.getId(), carrierType, role, privilegeBean, externalType);
Class clazz = Class.forName("com.fr.decision.webservice.v10.authority.AuthorityService");
Method method = clazz.getDeclaredMethod("updateAuthorityEntityByCarrier", String.class,String.class,String.class,PrivilegeBean.class,String.class);
method.invoke(AuthorityService.getInstance(),user.getId(), carrierType, role, privilegeBean, externalType);
//AuthorityService.getInstance().updateAuthorityEntityByCarrier(user.getId(), carrierType, role, privilegeBean, externalType);
}
private Map<String, String> getRoles() throws Exception {
List<CustomRole> customRoles = AuthorityContext.getInstance().getCustomRoleController().find(QueryFactory.create().addRestriction(RestrictionFactory.startWith("name", "WP_")));
if (customRoles == null || customRoles.isEmpty()) {
return new HashMap<>();
}
return customRoles.stream().collect(Collectors.toMap(CustomRole::getName, CustomRole::getId, (k1, k2) -> k2));
}
}

20
src/main/java/com/fr/plugin/xxxx/saml/xxxx/keystore/KeyInfoException.java

@ -0,0 +1,20 @@
package com.fr.plugin.xxxx.saml.xxxx.keystore;
public class KeyInfoException extends Exception {
private static final long serialVersionUID = 4122407041250537409L;
public KeyInfoException() {
}
public KeyInfoException(String paramString) {
super(paramString);
}
public KeyInfoException(String paramString, Throwable paramThrowable) {
super(paramString, paramThrowable);
}
public KeyInfoException(Throwable paramThrowable) {
super(paramThrowable);
}
}

56
src/main/java/com/fr/plugin/xxxx/saml/xxxx/keystore/KeystoreInfo.java

@ -0,0 +1,56 @@
package com.fr.plugin.xxxx.saml.xxxx.keystore;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
public class KeystoreInfo {
PublicKey publicKey = null;
PrivateKeyEntry privateKeyEntry = null;
public KeystoreInfo(InputStream jks, char[] storepass, char[] keypass, String alias)
throws KeyInfoException {
KeyStore ks = null;
try {
ks = KeyStore.getInstance("JKS");
ks.load(jks, storepass);
privateKeyEntry = (PrivateKeyEntry) ks.getEntry(alias,
new KeyStore.PasswordProtection(keypass));
if (ks.containsAlias(alias)) {
Key key = ks.getKey(alias, keypass);
if (key instanceof PrivateKey) {
Certificate cert = ks.getCertificate(alias);
publicKey = cert.getPublicKey();
} else {
throw new KeyInfoException("Private Key Not Exist");
}
} else {
throw new KeyInfoException("Alias Not Exist");
}
} catch (KeyStoreException e) {
throw new KeyInfoException(e.getMessage(),e);
} catch (NoSuchAlgorithmException e) {
throw new KeyInfoException(e.getMessage(),e);
} catch (CertificateException e) {
throw new KeyInfoException(e.getMessage(),e);
} catch (IOException e) {
throw new KeyInfoException(e.getMessage(),e);
} catch (UnrecoverableKeyException e) {
throw new KeyInfoException(e.getMessage(),e);
} catch (UnrecoverableEntryException e) {
throw new KeyInfoException(e.getMessage(),e);
}
}
public PrivateKeyEntry getPrivateKeyEntry() {
return privateKeyEntry;
}
public PublicKey getPublicKey() {
return publicKey;
}
}

137
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/SAMLAlgorithmUtil.java

@ -0,0 +1,137 @@
package com.fr.plugin.xxxx.saml.xxxx.saml;
import java.util.EnumMap;
public class SAMLAlgorithmUtil {
public enum DigestAlgorithmEnum {
SHA1("SHA1"), SHA224("SHA224"), SHA256("SHA256"), SHA384("SHA384"), SHA512(
"SHA512"), RIPEMD160("RIPEMD160") {
};
private String key;
private DigestAlgorithmEnum(String key) {
this.key = key;
}
public String getKey() {
return key;
}
}
public enum SignatureAlgorithmEnum {
DSA_SHA1("DSA_SHA1"), RSA_SHA1("RSA_SHA1"), HMAC_SHA1("HMAC_SHA1"), RSA_SHA224(
"RSA_SHA224"), RSA_SHA256("RSA_SHA256"), RSA_SHA384("RSA_SHA384"), RSA_SHA512(
"RSA_SHA512"), RSA_RIPEMD160("RSA_RIPEMD160"), ECDSA_SHA1(
"ECDSA_SHA1"), ECDSA_SHA224("ECDSA_SHA224"), ECDSA_SHA256(
"ECDSA_SHA256"), ECDSA_SHA384("ECDSA_SHA384"), ECDSA_SHA512(
"ECDSA_SHA512"), DSA_SHA256("DSA_SHA256") {
};
private String key;
private SignatureAlgorithmEnum(String key) {
this.key = key;
}
public String getKey() {
return key;
}
}
static EnumMap<DigestAlgorithmEnum, String> digestAlgorithmEnumMap = new EnumMap(
DigestAlgorithmEnum.class);
static EnumMap<SignatureAlgorithmEnum, String> signatureAlgorithmEnumMap = new EnumMap(
SignatureAlgorithmEnum.class);
static {
digestAlgorithmEnumMap.put(DigestAlgorithmEnum.SHA1,
"http://www.w3.org/2000/09/xmldsig#sha1");
digestAlgorithmEnumMap.put(DigestAlgorithmEnum.SHA224,
"http://www.w3.org/2001/04/xmldsig-more#sha224");
digestAlgorithmEnumMap.put(DigestAlgorithmEnum.SHA256,
"http://www.w3.org/2001/04/xmlenc#sha256");
digestAlgorithmEnumMap.put(DigestAlgorithmEnum.SHA384,
"http://www.w3.org/2001/04/xmldsig-more#sha384");
digestAlgorithmEnumMap.put(DigestAlgorithmEnum.SHA512,
"http://www.w3.org/2001/04/xmlenc#sha512");
digestAlgorithmEnumMap.put(DigestAlgorithmEnum.RIPEMD160,
"http://www.w3.org/2001/04/xmlenc#ripemd160");
signatureAlgorithmEnumMap.put(SignatureAlgorithmEnum.DSA_SHA1,
"http://www.w3.org/2000/09/xmldsig#dsa-sha1");
signatureAlgorithmEnumMap.put(SignatureAlgorithmEnum.RSA_SHA1,
"http://www.w3.org/2000/09/xmldsig#rsa-sha1");
signatureAlgorithmEnumMap.put(SignatureAlgorithmEnum.HMAC_SHA1,
"http://www.w3.org/2000/09/xmldsig#hmac-sha1");
signatureAlgorithmEnumMap.put(SignatureAlgorithmEnum.RSA_SHA224,
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha224");
signatureAlgorithmEnumMap.put(SignatureAlgorithmEnum.RSA_SHA256,
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
signatureAlgorithmEnumMap.put(SignatureAlgorithmEnum.RSA_SHA384,
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha384");
signatureAlgorithmEnumMap.put(SignatureAlgorithmEnum.RSA_SHA512,
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512");
signatureAlgorithmEnumMap.put(SignatureAlgorithmEnum.RSA_RIPEMD160,
"http://www.w3.org/2001/04/xmldsig-more#rsa-ripemd160");
signatureAlgorithmEnumMap.put(SignatureAlgorithmEnum.ECDSA_SHA1,
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1");
signatureAlgorithmEnumMap.put(SignatureAlgorithmEnum.ECDSA_SHA224,
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha224");
signatureAlgorithmEnumMap.put(SignatureAlgorithmEnum.ECDSA_SHA256,
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256");
signatureAlgorithmEnumMap.put(SignatureAlgorithmEnum.ECDSA_SHA384,
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384");
signatureAlgorithmEnumMap.put(SignatureAlgorithmEnum.ECDSA_SHA512,
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512");
signatureAlgorithmEnumMap.put(SignatureAlgorithmEnum.DSA_SHA256,
"http://www.w3.org/2009/xmldsig11#dsa-sha256");
}
public static String getDigestAlgorithmValue(String key) {
DigestAlgorithmEnum algorithm = getDigestAlgorithmEnum(key);
return digestAlgorithmEnumMap.get(algorithm);
}
private static DigestAlgorithmEnum getDigestAlgorithmEnum(String key) {
DigestAlgorithmEnum digestAlgorithmEnum = DigestAlgorithmEnum.SHA1;
for (DigestAlgorithmEnum algorithmEnum : DigestAlgorithmEnum.values()) {
String algorithmKey = algorithmEnum.getKey();
if (algorithmKey.equals(key)) {
digestAlgorithmEnum = algorithmEnum;
break;
}
}
return digestAlgorithmEnum;
}
public static String getSignatureAlgorithmValue(String key) {
SignatureAlgorithmEnum algorithm = getSignatureAlgorithmEnum(key);
return signatureAlgorithmEnumMap.get(algorithm);
}
private static SignatureAlgorithmEnum getSignatureAlgorithmEnum(String key) {
//默认RSA_SHA1
SignatureAlgorithmEnum signatureAlgorithmEnum = SignatureAlgorithmEnum.RSA_SHA1;
for (SignatureAlgorithmEnum algorithmEnum : SignatureAlgorithmEnum
.values()) {
String algorithmKey = algorithmEnum.getKey();
if (algorithmKey.equals(key)) {
signatureAlgorithmEnum = algorithmEnum;
break;
}
}
return signatureAlgorithmEnum;
}
}

20
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/SAMLException.java

@ -0,0 +1,20 @@
package com.fr.plugin.xxxx.saml.xxxx.saml;
public class SAMLException extends Exception {
private static final long serialVersionUID = 1L;
public SAMLException() {
}
public SAMLException(Throwable e) {
super(e);
}
public SAMLException(String message) {
super(message);
}
public SAMLException(String message, Throwable e) {
super(message, e);
}
}

5
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/SAMLRequest.java

@ -0,0 +1,5 @@
package com.fr.plugin.xxxx.saml.xxxx.saml;
public interface SAMLRequest {
public String generate() throws SAMLException;
}

45
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/SAMLResponse.java

@ -0,0 +1,45 @@
package com.fr.plugin.xxxx.saml.xxxx.saml;
import com.fr.plugin.xxxx.saml.xxxx.saml.bean.UserInfoBean;
import org.w3c.dom.Node;
public interface SAMLResponse {
public String getIssuer();
public String getNotBefore();
public String getNotOnOrAfter();
public Node getSignature();
public String getNameId();
public String getCn();
public String getSn();
public String getGivenName();
public String getDisplayName();
public String getEmployeeNumber();
public String getEmployeeType();
public String getUid();
public String getUuid();
public String getTelephoneNumber();
public String getMail();
public String getDepartmentName();
public String getSource();
public String getRegisterPhone();
public UserInfoBean getUIBean();
}

37
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/SAMLResponseValidator.java

@ -0,0 +1,37 @@
package com.fr.plugin.xxxx.saml.xxxx.saml;
import com.fr.plugin.xxxx.saml.xxxx.saml.bean.UserInfoBean;
public interface SAMLResponseValidator {
public void validate() throws SAMLException;
public String getNameId();
public String getCn();
public String getSn();
public String getGivenName();
public String getDisplayName();
public String getEmployeeNumber();
public String getEmployeeType();
public String getUid();
public String getUuid();
public String getTelephoneNumber();
public String getMail();
public String getDepartmentName();
public String getSource();
public String getRegisterPhone();
public UserInfoBean getUIBean();
}

204
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/SAMLUtil.java

@ -0,0 +1,204 @@
package com.fr.plugin.xxxx.saml.xxxx.saml;
import org.apache.jcp.xml.dsig.internal.dom.DOMTransform;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.input.DOMBuilder;
import org.jdom.output.XMLOutputter;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
import javax.xml.XMLConstants;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dsig.*;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.io.StringWriter;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.cert.X509Certificate;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class SAMLUtil {
public static String toStanderTime(Date date) {
SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
TimeZone zone = TimeZone.getTimeZone("GMT");
dayFormat.setTimeZone(zone);
timeFormat.setTimeZone(zone);
return dayFormat.format(date) + 'T' + timeFormat.format(date) + 'Z';
}
public static Calendar toDate(String t) {
String date = t.substring(0, t.indexOf("T"));
String time = t.substring(t.indexOf("T") + 1, t.length() - 1);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
// Time in GMT
TimeZone zone = TimeZone.getTimeZone("GMT");
dateFormat.setTimeZone(zone);
timeFormat.setTimeZone(zone);
try {
Date dd = dateFormat.parse(date);
Date tt = timeFormat.parse(time);
long m = dd.getTime() + tt.getTime();
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(m);
return cal;
} catch (ParseException e) {
throw new IllegalArgumentException("Invalid SAML time");
}
}
public static void addNamespace(Element root, Namespace namespace) {
if (root == null) {
return;
}
root.setNamespace(namespace);
if (root.getChildren() == null) {
return;
}
for (int index = 0; index < root.getChildren().size(); index++) {
Element child = (Element) root.getChildren().get(index);
addNamespace(child, namespace);
}
}
public static void insertSignature(org.w3c.dom.Element element,
PrivateKeyEntry privateKey, Node insertBefore) throws SAMLException {
String digestAlgorithm = SAMLAlgorithmUtil.getDigestAlgorithmValue(SAMLAlgorithmUtil.DigestAlgorithmEnum.SHA1.getKey());
String signatureAlgorithm = SAMLAlgorithmUtil.getSignatureAlgorithmValue(SAMLAlgorithmUtil.SignatureAlgorithmEnum.RSA_SHA1.getKey());
signSignature(element, privateKey, insertBefore, digestAlgorithm,
signatureAlgorithm);
}
public static void insertSignature(org.w3c.dom.Element element,
PrivateKeyEntry privateKey, Node insertBefore, String digestAlgorithm,String signatureAlgorithm)
throws SAMLException {
signSignature(element, privateKey, insertBefore,
digestAlgorithm,signatureAlgorithm);
}
private static void signSignature(org.w3c.dom.Element element,
PrivateKeyEntry privateKey, Node insertBefore,String digestAlgorithm ,String signatureAlgorithm) throws SAMLException {
String JSR_105_PROVIDER = "org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI";
String providerName = System.getProperty("jsr105Provider",
JSR_105_PROVIDER);
try {
Provider provider = (Provider) Class.forName(providerName).newInstance();
// 创建XML签名工厂
XMLSignatureFactory factory = XMLSignatureFactory.getInstance("DOM", provider);
TransformService ts = TransformService.getInstance(Transform.ENVELOPED, "DOM", provider);
DOMTransform domTrasform = new DOMTransform(ts);
CanonicalizationMethod canMethod = factory.newCanonicalizationMethod(
CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null);
element.setIdAttribute("ID", true);
String refId = element.getAttribute("ID");
//消息摘要包括:MD(Message Digest,消息摘要算法)、SHA(Secure Hash Algorithm,安全散列算法)、MAC(Message AuthenticationCode,消息认证码算法)
//这里采用 安全散列算法SHA
Reference ref = factory.newReference("#" + refId,
factory.newDigestMethod(SAMLAlgorithmUtil.getDigestAlgorithmValue(digestAlgorithm), null),
Collections.singletonList(domTrasform), null, null);
// SignatureMethod signatureMethod = factory.newSignatureMethod(
// SignatureMethod.RSA_SHA1, null);
// 数字签名算法 MD5和SHA1分别是MD、SHA算法系列中最有代表性的算法
SignatureMethod signatureMethod = factory.newSignatureMethod(
SAMLAlgorithmUtil.getSignatureAlgorithmValue(signatureAlgorithm), null);
SignedInfo signedInfo = factory.newSignedInfo(canMethod,
signatureMethod, Collections.singletonList(ref));
X509Certificate cert = (X509Certificate) privateKey.getCertificate();
KeyInfoFactory kif = factory.getKeyInfoFactory();
List<Serializable> x509Content = new ArrayList<Serializable>();
x509Content.add(cert);
X509Data xd = kif.newX509Data(x509Content);
KeyInfo keyInfo = kif.newKeyInfo(Collections.singletonList(xd));
PrivateKey key = privateKey.getPrivateKey();
DOMSignContext dsc = new DOMSignContext(key, element);
dsc.setNextSibling(insertBefore);
XMLSignature signature = factory.newXMLSignature(signedInfo,keyInfo);
signature.sign(dsc);
} catch (IllegalAccessException e) {
throw new SAMLException("Error insertSignature:" + e.getMessage(),e);
} catch (MarshalException e) {
throw new SAMLException("Error insertSignature:" + e.getMessage(),e);
} catch (XMLSignatureException e) {
throw new SAMLException("Error insertSignature:" + e.getMessage(),e);
} catch (InstantiationException e) {
throw new SAMLException("Error insertSignature:" + e.getMessage(),e);
} catch (ClassNotFoundException e) {
throw new SAMLException("Error insertSignature:" + e.getMessage(),e);
} catch (NoSuchAlgorithmException e) {
throw new SAMLException("Error insertSignature:" + e.getMessage(),e);
} catch (InvalidAlgorithmParameterException e) {
throw new SAMLException("Error insertSignature:" + e.getMessage(),e);
}
}
public static org.w3c.dom.Document toDom(org.jdom.Document doc)
throws SAMLException {
try {
XMLOutputter xmlOutputter = new XMLOutputter();
StringWriter elemStrWriter = new StringWriter();
xmlOutputter.output(doc, elemStrWriter);
byte[] xmlBytes = elemStrWriter.toString().getBytes();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
setDocumentBuilderFeature(dbf);
return dbf.newDocumentBuilder().parse(
new ByteArrayInputStream(xmlBytes));
} catch (IOException e) {
throw new SAMLException("Error JDOM to W3 DOM: " + e.getMessage(), e);
} catch (ParserConfigurationException e) {
throw new SAMLException("Error JDOM to W3 DOM: " + e.getMessage(), e);
} catch (SAXException e) {
throw new SAMLException("Error JDOM to W3 DOM: " + e.getMessage(), e);
}
}
public static org.w3c.dom.Element toDom(org.jdom.Element element)
throws SAMLException {
org.jdom.Document doc = element.getDocument();
if (doc == null) {
throw new SAMLException("Invalid JDOM element");
}
return toDom(element.getDocument()).getDocumentElement();
}
public static org.jdom.Element toJdom(org.w3c.dom.Element e) {
DOMBuilder builder = new DOMBuilder();
org.jdom.Element jdomElem = builder.build(e);
return jdomElem;
}
public static void setDocumentBuilderFeature(DocumentBuilderFactory dbf)
throws ParserConfigurationException {
//必选
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,true );
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
//必选
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
}
}

23
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/ServiceProvider.java

@ -0,0 +1,23 @@
package com.fr.plugin.xxxx.saml.xxxx.saml;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.PublicKey;
import java.security.cert.Certificate;
public interface ServiceProvider {
public String getIssuer();
public String getServiceUrl();
public PrivateKeyEntry getPrivateKeyEntry();
public PublicKey getPublicKey();
public Certificate getCertificate();
/**
* 消息摘要算法
* @return
*/
public String getDigestAlgorithm();
/**
* 签名算法
* @return
*/
public String getSignatureAlgorithm();
}

80
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/assertion/AuthnRequest.java

@ -0,0 +1,80 @@
package com.fr.plugin.xxxx.saml.xxxx.saml.assertion;
import com.fr.plugin.xxxx.saml.xxxx.saml.response.UuidGenerator;
import org.jdom.Element;
import org.jdom.Namespace;
public class AuthnRequest {
public static final Namespace samlp = Namespace.getNamespace("samlp",
"urn:oasis:names:tc:SAML:2.0:protocol");
public static final Namespace saml = Namespace.getNamespace("saml",
"urn:oasis:names:tc:SAML:2.0:assertion");
private String issuer;
private String issueInstant;
private String serviceUrl;
private String digestAlgorithm;
private String signatureAlgorithm;
public AuthnRequest(String issuer,String issueInstant,String serviceUrl){
this.issuer = issuer;
this.issueInstant = issueInstant;
this.serviceUrl = serviceUrl;
}
public Element toXML() {
Element request = new Element("AuthnRequest");
request.setAttribute("ID",new UuidGenerator().generate());
request.setAttribute("Version","2.0");
request.setAttribute("IssueInstant",this.issueInstant);
request.setAttribute("ProtocolBinding","urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST");
request.setAttribute("AssertionConsumerServiceIndex","0");
request.setAttribute("AssertionConsumerServiceURL",this.serviceUrl);
request.setAttribute("AttributeConsumingServiceIndex","0");
request.setAttribute("source","http://xxx.huawei.com/yyy");
request.setAttribute("uiType","0");
if (null != digestAlgorithm) {
request.setAttribute("digestAlgorithm", digestAlgorithm);
}
if (null != signatureAlgorithm) {
request.setAttribute("signatureAlgorithm", signatureAlgorithm);
}
Element issuerElement = new Element("Issuer");
issuerElement.addContent(this.issuer);
issuerElement.setNamespace(saml);
Element nameIDPolicy = new Element("NameIDPolicy");
nameIDPolicy.setAttribute("AllowCreate","False");
nameIDPolicy.setNamespace(samlp);
request.addContent(issuerElement);
request.addContent(nameIDPolicy);
request.setNamespace(samlp);
return request;
}
public String getDigestAlgorithm() {
return digestAlgorithm;
}
public void setDigestAlgorithm(String digestAlgorithm) {
this.digestAlgorithm = digestAlgorithm;
}
public String getSignatureAlgorithm() {
return signatureAlgorithm;
}
public void setSignatureAlgorithm(String signatureAlgorithm) {
this.signatureAlgorithm = signatureAlgorithm;
}
}

1220
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/bean/UserInfoBean.java

File diff suppressed because it is too large Load Diff

5
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/constant/SsoConstants.java

@ -0,0 +1,5 @@
package com.fr.plugin.xxxx.saml.xxxx.saml.constant;
public class SsoConstants {
public static String SESSION_USER_INFO_KEY = "_SESSION_USER_INFO";
}

19
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/filter/EncodingFilter.java

@ -0,0 +1,19 @@
package com.fr.plugin.xxxx.saml.xxxx.saml.filter;
import javax.servlet.*;
import java.io.IOException;
public class EncodingFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
chain.doFilter(req, resp);
}
public void destroy() {
}
}

131
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/filter/SAMLFilter.java

@ -0,0 +1,131 @@
package com.fr.plugin.xxxx.saml.xxxx.saml.filter;
import com.fr.plugin.xxxx.saml.xxxx.saml.SAMLException;
import com.fr.plugin.xxxx.saml.xxxx.saml.SAMLResponseValidator;
import com.fr.plugin.xxxx.saml.xxxx.saml.bean.UserInfoBean;
import com.fr.plugin.xxxx.saml.xxxx.saml.constant.SsoConstants;
import com.fr.plugin.xxxx.saml.xxxx.saml.impl.SAMLRequestImpl;
import com.fr.plugin.xxxx.saml.xxxx.saml.impl.SAMLResponseValidatorImpl;
import org.apache.commons.codec.binary.Base64;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class SAMLFilter implements Filter {
private static final String returnPage = "/WEB-INF/pages/index.jsp";
private static final String logon = "/WEB-INF/pages/logon.jsp";
private String[] exclusions;
public void init(FilterConfig filterConfig) throws ServletException {
String exclusionsStr = filterConfig.getInitParameter("exclusions");
if (exclusionsStr.trim().length() > 0) {
exclusions = exclusionsStr.split(",");
}
}
/**判断是否绕过过滤器**/
private boolean isexclusion(String currentURL) {
if (exclusions == null || exclusions.length < 1 || currentURL == null || currentURL.length() < 1)
return false;
for (int i = 0; i < exclusions.length; i++)
if (currentURL.matches(exclusions[i].replaceAll("\\*", "\\.\\*")))
return true;
return false;
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
HttpSession session = request.getSession();
//绕过过滤器
if (request.getRequestURL() != null && isexclusion(request.getRequestURL().toString())) {
chain.doFilter(req, resp);
return;
}
// 判断是否已经建立用户
if (session == null || session.getAttribute(SsoConstants.SESSION_USER_INFO_KEY) == null) {
String samlResp = request.getParameter("SAMLResponse");
if (samlResp != null && !samlResp.equals("")) {
byte[] buffer = new Base64().decode(samlResp.getBytes(StandardCharsets.UTF_8));
try {
// System.out.println(new
// String(buffer,StandardCharsets.UTF_8));
SAMLResponseValidator vld = new SAMLResponseValidatorImpl(
new String(buffer, StandardCharsets.UTF_8));
vld.validate();
// 帐号
// System.err.println("登陆账号:" +vld.getNameId());
// 附加字段
UserInfoBean uiBean = vld.getUIBean();
// System.err.println("::::getCn=" + uiBean.getCn());
// System.err.println("::::getSn=" + uiBean.getSn());
// System.err.println("::::getGivenName=" +
// uiBean.getGivenName());
// System.err.println("::::getEmployeeNumber=" +
// uiBean.getEmployeeNumber());
// System.err.println("::::getEmployeeType=" +
// uiBean.getEmployeeType());
// 需要注意,默认W3账号只返回工号,外网帐号返回帐号名
// System.err.println("::::getUid=" + uiBean.getUid());
// System.err.println("::::getUuid=" +
// uiBean.getProperty("uuid"));
// System.err.println("::::getTelephoneNumber=" +
// uiBean.getProperty(UserInfoBean.KEY_TELEPHONENUMBER));
// System.err.println("::::getSource=" + vld.getSource());
// System.err.println("::::getMail=" +
// uiBean.getFirstEmail());
// System.err.println("::::getRegisterPhone=" +
// uiBean.getProperty("registerphone"));
session.setAttribute(SsoConstants.SESSION_USER_INFO_KEY, uiBean);
} catch (SAMLException e) {
e.printStackTrace();
request.setAttribute("error", e.getMessage());
}
} else {
try {
byte[] samlRequest = new SAMLRequestImpl().generate().getBytes(StandardCharsets.UTF_8);
samlRequest = new Base64().encode(samlRequest);
// System.out.println("samlRequest::::" + new
// String(samlRequest));
// System.out.println("samlRequest::==::" + new
// SAMLRequestImpl().generate());
request.setAttribute("SAMLRequest", new String(samlRequest, StandardCharsets.UTF_8));
request.getRequestDispatcher(returnPage).forward(request, response);
return;
} catch (SAMLException e) {
e.printStackTrace();
request.setAttribute("SAMLRequest", e.getMessage());
}
}
}
UserInfoBean uiBean = (UserInfoBean) session.getAttribute(SsoConstants.SESSION_USER_INFO_KEY);
if (uiBean != null) {
String nameId = uiBean.getNameId();
// System.err.println("uid=" + uid);
request.setAttribute("nameId",nameId);
}
request.getRequestDispatcher(logon).forward(request, response);
// chain.doFilter(req, resp);
}
public void destroy() {
}
}

18
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/impl/SAMLRequestImpl.java

@ -0,0 +1,18 @@
package com.fr.plugin.xxxx.saml.xxxx.saml.impl;
import com.fr.plugin.xxxx.saml.xxxx.saml.SAMLException;
import com.fr.plugin.xxxx.saml.xxxx.saml.SAMLRequest;
import com.fr.plugin.xxxx.saml.xxxx.saml.ServiceProvider;
import com.fr.plugin.xxxx.saml.xxxx.saml.response.RequestBuilder;
public class SAMLRequestImpl implements SAMLRequest {
@Override
public String generate() throws SAMLException {
ServiceProvider sp = new ServiceProviderImpl();
RequestBuilder requestBuilder = new RequestBuilder(sp.getIssuer(), sp.getServiceUrl(),
sp.getPrivateKeyEntry());
requestBuilder.setDigestAlgorithm(sp.getDigestAlgorithm());
requestBuilder.setSignatureAlgorithm(sp.getSignatureAlgorithm());
return requestBuilder.build();
}
}

262
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/impl/SAMLResponseImpl.java

@ -0,0 +1,262 @@
package com.fr.plugin.xxxx.saml.xxxx.saml.impl;
import com.fr.plugin.xxxx.saml.xxxx.saml.SAMLException;
import com.fr.plugin.xxxx.saml.xxxx.saml.SAMLResponse;
import com.fr.plugin.xxxx.saml.xxxx.saml.SAMLUtil;
import com.fr.plugin.xxxx.saml.xxxx.saml.bean.UserInfoBean;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
public class SAMLResponseImpl implements SAMLResponse {
private String issuer;
private String notBefore;
private String notOnOrAfter;
private Node signature;
private String nameId;
private String cn;
private String sn;
private String givenName;
private String displayName;
private String employeeNumber;
private String employeeType;
private String uid;
private String uuid;
private String telephoneNumber;
private String mail;
private String departmentName;
private String source;
private String registerPhone;
private UserInfoBean uiBean = new UserInfoBean(UserInfoBean.INTERNET_USER);
public SAMLResponseImpl(String response) throws SAMLException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);
dbf.setNamespaceAware(true);
Document doc;
try {
SAMLUtil.setDocumentBuilderFeature(dbf);
ByteArrayInputStream bais = new ByteArrayInputStream(response.getBytes("UTF-8"));
doc = dbf.newDocumentBuilder().parse(bais);
doc.getDocumentElement().setIdAttribute("ID", true);
} catch (SAXException e) {
throw new SAMLException("Invalid SAML response", e);
} catch (IOException e) {
throw new SAMLException("Invalid SAML response", e);
} catch (ParserConfigurationException e) {
throw new SAMLException("Invalid SAML response", e);
}
String issuer = getIssuer(doc);
if (issuer != null) {
this.issuer = issuer;
} else {
throw new SAMLException("Invalid SAML response: miss <Issuer>");
}
Element condition = getCondition(doc);
if (condition != null) {
this.notBefore = condition.getAttribute("NotBefore");
this.notOnOrAfter = condition.getAttribute("NotOnOrAfter");
} else {
throw new SAMLException("Invalid SAML response: miss <Conditions>");
}
Node signature = getSignature(doc);
if (signature != null) {
this.signature = signature;
} else {
throw new SAMLException("Invalid SAML response: miss <Signature>");
}
String nameId = getNameId(doc);
if (nameId != null) {
this.nameId = nameId;
} else {
throw new SAMLException("Invalid SAML response: miss <NameId>");
}
uiBean.setNameId(nameId);
this.cn = getElementValue(doc, "cn");
uiBean.setCn(cn);
uiBean.setProperties(UserInfoBean.KEY_CN, cn);
this.sn = getElementValue(doc, "sn");
uiBean.setSn(sn);
uiBean.setProperties(UserInfoBean.KEY_SN, sn);
this.givenName = getElementValue(doc, "givenName");
uiBean.setGivenName(givenName);
uiBean.setProperties(UserInfoBean.KEY_GIVENNAME, givenName);
this.displayName = getElementValue(doc, "displayName");
this.departmentName = getElementValue(doc, "departmentName");
this.uid = getElementValue(doc, "uid");
uiBean.setUid(uid);
uiBean.setProperties(UserInfoBean.KEY_UID, uid);
this.uuid = getElementValue(doc, "uuid");
uiBean.setProperties("uuid", uuid);
this.telephoneNumber = getElementValue(doc, "telephoneNumber");
uiBean.setProperties(UserInfoBean.KEY_TELEPHONENUMBER, telephoneNumber);
this.mail = getElementValue(doc, "mail");
uiBean.setEmail(mail);
uiBean.setProperties(UserInfoBean.KEY_MAIL, mail);
this.employeeNumber = getElementValue(doc, "employeeNumber");
uiBean.setEmployeeNumber(employeeNumber);
uiBean.setProperties(UserInfoBean.KEY_EMPLOYEENUMBER, employeeNumber);
this.employeeType = getElementValue(doc, "employeeType");
uiBean.setEmployeeType(employeeType);
uiBean.setProperties(UserInfoBean.KEY_EMPLOYEETYPE, employeeType);
this.source = getElementValue(doc, "source");
this.registerPhone = getElementValue(doc, "registerphone");
uiBean.setProperties("registerphone", registerPhone);
}
public String getIssuer() {
return issuer;
}
public String getNotBefore() {
return notBefore;
}
public String getNotOnOrAfter() {
return notOnOrAfter;
}
public Node getSignature() {
return signature;
}
public String getNameId() {
return nameId;
}
public String getCn() {
return cn;
}
public String getSn() {
return sn;
}
public String getGivenName() {
return givenName;
}
public String getDisplayName() {
return displayName;
}
public String getEmployeeNumber() {
return employeeNumber;
}
public String getEmployeeType() {
return employeeType;
}
public String getRegisterPhone() {
return registerPhone;
}
public String getUid() {
return uid;
}
public String getUuid() {
return uuid;
}
public String getTelephoneNumber() {
return telephoneNumber;
}
public String getMail() {
return mail;
}
public String getDepartmentName() {
return departmentName;
}
public String getSource() {
return source;
}
public UserInfoBean getUIBean() {
return uiBean;
}
private String getIssuer(Document doc) {
NodeList nl = doc.getElementsByTagNameNS("*", "Issuer");
if (nl.getLength() != 0) {
return nl.item(0).getTextContent();
}
return null;
}
private Element getCondition(Document doc) throws SAMLException {
NodeList nl = doc.getElementsByTagNameNS("*", "Conditions");
if (nl.getLength() != 0) {
return (Element) nl.item(0);
}
return null;
}
private Node getSignature(Document doc) {
NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
if (nl.getLength() != 0) {
return nl.item(0);
}
return null;
}
private String getNameId(Document doc) {
NodeList nl = doc.getElementsByTagNameNS("*", "NameID");
if (nl.getLength() != 0) {
return nl.item(0).getTextContent();
}
return null;
}
public static String getElementValue(Document doc, String elementName) {
NodeList list = doc.getChildNodes();
Node root = list.item(0);
HashMap resultMap = getElementValueByName(root, elementName);
return (String) resultMap.get("elementValue");
}
public static HashMap getElementValueByName(Node node, String elementName) {
HashMap resultMap = new HashMap();
resultMap.put("found", "false");
NamedNodeMap nodeMap = node.getAttributes();
if (nodeMap != null) {
for (int j = 0; j < nodeMap.getLength(); j++) {
String attrName = nodeMap.item(j).getNodeName();
String attrValue = nodeMap.item(j).getNodeValue();
if ("FriendlyName".equalsIgnoreCase(attrName) && elementName.equalsIgnoreCase(attrValue)) {
resultMap.put("elementValue", node.getTextContent());
resultMap.put("found", "true");
// System.err.println(elementName + "@@@@@@" +
// node.getTextContent());
break;
}
}
}
if ("true".equals((String) resultMap.get("found"))) {
return resultMap;
} else {
NodeList childList = node.getChildNodes();
if (childList != null && childList.getLength() > 0) {
for (int i = 0; i < childList.getLength(); i++) {
Node childElement = childList.item(i);
resultMap = getElementValueByName(childElement, elementName);
if ("true".equals((String) resultMap.get("found"))) {
break;
}
}
}
}
return resultMap;
}
}

180
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/impl/SAMLResponseValidatorImpl.java

@ -0,0 +1,180 @@
package com.fr.plugin.xxxx.saml.xxxx.saml.impl;
import com.fr.plugin.xxxx.saml.xxxx.saml.*;
import com.fr.plugin.xxxx.saml.xxxx.saml.bean.UserInfoBean;
import org.w3c.dom.Node;
import javax.xml.crypto.MarshalException;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureException;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import java.security.Provider;
import java.security.PublicKey;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.Calendar;
import java.util.Date;
public class SAMLResponseValidatorImpl implements SAMLResponseValidator {
private static final String JSR_105_PROVIDER = "org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI";
private SAMLResponse response;
private ServiceProvider provider;
public SAMLResponseValidatorImpl(String response) throws SAMLException {
this.response = new SAMLResponseImpl(response);
this.provider = new ServiceProviderImpl();
}
public void validate() throws SAMLException {
if (!validServiceProvider()) {
throw new SAMLException("UnknownServiceProvider");
}
if (timeNoReache()) {
throw new SAMLException("TimeNoReache");
}
if (expire()) {
throw new SAMLException("Expire");
}
if (!validCertificate()) {
throw new SAMLException("InValidCertificate");
}
if (!isValidXMLSign()) {
throw new SAMLException("InValidSignature");
}
}
public String getUserId() {
return response.getNameId();
}
private boolean validServiceProvider() {
return response.getIssuer().equalsIgnoreCase("www.huawei.com");
}
private boolean timeNoReache() {
Calendar now = Calendar.getInstance();
return SAMLUtil.toDate(response.getNotBefore()).after(now);
}
private boolean expire() {
Calendar now = Calendar.getInstance();
return SAMLUtil.toDate(response.getNotOnOrAfter()).before(now);
}
private boolean validCertificate() throws SAMLException {
try {
((X509Certificate) provider.getCertificate()).checkValidity(new Date());
} catch (CertificateExpiredException e) {
throw new SAMLException(e);
} catch (CertificateNotYetValidException e) {
throw new SAMLException(e);
}
return true;
}
public boolean isValidXMLSign() throws SAMLException {
boolean coreValidity = false;
Node signatreuNode = response.getSignature();
String providerName = System.getProperty("jsr105Provider", JSR_105_PROVIDER);
XMLSignatureFactory fac;
try {
fac = XMLSignatureFactory.getInstance("DOM", (Provider) Class.forName(providerName).newInstance());
} catch (IllegalAccessException e) {
throw new SAMLException("Cannot instance XMLSignatureFactory");
} catch (InstantiationException e) {
throw new SAMLException("Cannot instance XMLSignatureFactory");
} catch (ClassNotFoundException e) {
throw new SAMLException("Cannot instance XMLSignatureFactory");
}
X509Certificate x509Certificate = (X509Certificate) provider.getCertificate();
PublicKey publicKey = x509Certificate.getPublicKey();
DOMValidateContext valContext = new DOMValidateContext(publicKey, signatreuNode);
try {
XMLSignature signature = fac.unmarshalXMLSignature(valContext);
coreValidity = signature.validate(valContext);
} catch (MarshalException e) {
throw new SAMLException("Cannot unmarshalXMLSignature:" + e.getMessage(), e);
} catch (XMLSignatureException e) {
throw new SAMLException("XMLSignatureException:" + e.getMessage(), e);
}
return coreValidity;
}
@Override
public String getNameId() {
return response.getNameId();
}
@Override
public String getCn() {
return response.getCn();
}
@Override
public String getSn() {
return response.getSn();
}
@Override
public String getGivenName() {
return response.getGivenName();
}
@Override
public String getDisplayName() {
return response.getDisplayName();
}
@Override
public String getEmployeeNumber() {
return response.getEmployeeNumber();
}
@Override
public String getEmployeeType() {
return response.getEmployeeType();
}
@Override
public String getUid() {
return response.getUid();
}
@Override
public String getUuid() {
return response.getUuid();
}
@Override
public String getRegisterPhone() {
return response.getRegisterPhone();
}
@Override
public String getTelephoneNumber() {
return response.getTelephoneNumber();
}
@Override
public String getMail() {
return response.getMail();
}
@Override
public String getDepartmentName() {
return response.getDepartmentName();
}
@Override
public String getSource() {
return response.getSource();
}
@Override
public UserInfoBean getUIBean() {
return response.getUIBean();
}
}

115
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/impl/ServiceProviderImpl.java

@ -0,0 +1,115 @@
package com.fr.plugin.xxxx.saml.xxxx.saml.impl;
import com.fr.plugin.xxxx.saml.xxxx.keystore.KeyInfoException;
import com.fr.plugin.xxxx.saml.xxxx.keystore.KeystoreInfo;
import com.fr.plugin.xxxx.saml.xxxx.saml.ServiceProvider;
import com.fr.plugin.xxxx.saml.xxxx.security.AESUtil;
import com.fr.plugin.xxxx.saml.xxxx.security.EncryptException;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore.PrivateKeyEntry;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Properties;
public class ServiceProviderImpl implements ServiceProvider {
private static String issuer;
private static String serviceUrl;
private static KeystoreInfo keyInfo;
private static Certificate certificate;
private static String digestAlgorithm;
private static String signatureAlgorithm;
static {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
InputStream is = null;
InputStream jks = null;
InputStream cer = null;
Properties properties = new Properties();
try {
is = cl.getResourceAsStream("saasclient.properties");
properties.load(is);
issuer = properties.getProperty("issuer");
serviceUrl = properties.getProperty("serviceurl");
String store = properties.getProperty("keystore");
jks = cl.getResourceAsStream(store);
String spass = AESUtil.decrypt(properties.getProperty("storepassword"));
String kpass = AESUtil.decrypt(properties.getProperty("keypassword"));
String alias = properties.getProperty("keyalias");
keyInfo = new KeystoreInfo(jks, spass.toCharArray(), kpass.toCharArray(), alias);
CertificateFactory caf = CertificateFactory.getInstance("X.509");
cer = cl.getResourceAsStream(properties.getProperty("certificatepath"));
certificate = caf.generateCertificate(cer);
digestAlgorithm = properties.getProperty("digestAlgorithm");
signatureAlgorithm = properties.getProperty("signatureAlgorithm");
} catch (IOException e) {
throw new RuntimeException(e);
} catch (EncryptException e) {
throw new RuntimeException(e);
} catch (KeyInfoException e) {
throw new RuntimeException(e);
} catch (CertificateException e) {
throw new RuntimeException(e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
if (jks != null) {
try {
jks.close();
} catch (IOException e) {
}
}
if (cer != null) {
try {
cer.close();
} catch (IOException e) {
}
}
}
}
@Override
public String getIssuer() {
return issuer;
}
@Override
public String getServiceUrl() {
return serviceUrl;
}
@Override
public PrivateKeyEntry getPrivateKeyEntry() {
return keyInfo.getPrivateKeyEntry();
}
@Override
public PublicKey getPublicKey() {
return keyInfo.getPublicKey();
}
@Override
public Certificate getCertificate() {
return certificate;
}
@Override
public String getDigestAlgorithm() {
return digestAlgorithm;
}
@Override
public String getSignatureAlgorithm() {
return signatureAlgorithm;
}
}

41
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/response/Request.java

@ -0,0 +1,41 @@
package com.fr.plugin.xxxx.saml.xxxx.saml.response;
import com.fr.plugin.xxxx.saml.xxxx.saml.SAMLException;
import com.fr.plugin.xxxx.saml.xxxx.saml.SAMLUtil;
import com.fr.plugin.xxxx.saml.xxxx.saml.assertion.AuthnRequest;
import org.jdom.Document;
import org.jdom.Element;
import org.w3c.dom.NodeList;
import java.security.KeyStore.PrivateKeyEntry;
public class Request {
private AuthnRequest request;
private PrivateKeyEntry privateKey;
public Request(AuthnRequest request, PrivateKeyEntry privateKey) {
this.request = request;
this.privateKey = privateKey;
}
public Element toXML() throws SAMLException {
Element req = request.toXML();
if(privateKey != null) {
Document doc = new Document();
doc.setRootElement(req);
org.w3c.dom.Element element = SAMLUtil.toDom(req);
NodeList nodeList = element.getElementsByTagNameNS(AuthnRequest.saml.getURI(),"Issuer");
org.w3c.dom.Node insertBefore = nodeList.item(nodeList.getLength() - 1);
SAMLUtil.insertSignature(element, privateKey, insertBefore,request.getDigestAlgorithm(),request.getSignatureAlgorithm());
req = SAMLUtil.toJdom(element);
req.detach();
}
return req;
}
}

49
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/response/RequestBuilder.java

@ -0,0 +1,49 @@
package com.fr.plugin.xxxx.saml.xxxx.saml.response;
import com.fr.plugin.xxxx.saml.xxxx.saml.SAMLException;
import com.fr.plugin.xxxx.saml.xxxx.saml.assertion.AuthnRequest;
import org.jdom.Document;
import org.jdom.output.XMLOutputter;
import java.security.KeyStore.PrivateKeyEntry;
public class RequestBuilder {
private String issuer;
private String serviceUrl;
private PrivateKeyEntry privateKeyEntry;
private String digestAlgorithm;
private String signatureAlgorithm;
public RequestBuilder(String issuer,String serviceUrl,PrivateKeyEntry privateKeyEntry) {
this.issuer = issuer;
this.serviceUrl = serviceUrl;
this.privateKeyEntry = privateKeyEntry;
}
public String build() throws SAMLException {
AuthnRequest authnRequest = new AuthnRequest(this.issuer,
this.issuer, this.serviceUrl);
authnRequest.setDigestAlgorithm(digestAlgorithm);
authnRequest.setSignatureAlgorithm(signatureAlgorithm);
Request request = new Request(authnRequest,this.privateKeyEntry);
Document doc = new Document().setRootElement(request.toXML());
return new XMLOutputter().outputString(doc);
}
public String getDigestAlgorithm() {
return digestAlgorithm;
}
public void setDigestAlgorithm(String digestAlgorithm) {
this.digestAlgorithm = digestAlgorithm;
}
public String getSignatureAlgorithm() {
return signatureAlgorithm;
}
public void setSignatureAlgorithm(String signatureAlgorithm) {
this.signatureAlgorithm = signatureAlgorithm;
}
}

27
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/response/UuidGenerator.java

@ -0,0 +1,27 @@
package com.fr.plugin.xxxx.saml.xxxx.saml.response;
import java.security.SecureRandom;
public class UuidGenerator {
private static final char[] charMapping = { '0', '1', '2', '3', '4', '5',
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
public String generate() {
byte[] bytes = new byte[20];
SecureRandom random = new SecureRandom();
random.nextBytes(bytes);
char[] chars = new char[40];
for (int i = 0; i < bytes.length; i++) {
int left = (bytes[i] >> 4) & 0x0f;
int right = bytes[i] & 0x0f;
chars[i * 2] = charMapping[left];
chars[i * 2 + 1] = charMapping[right];
}
return "s2" + String.valueOf(chars);
}
// public static void main(String[] args) {
// UuidGenerator xx = new UuidGenerator();
// System.err.println(xx.generate());
// }
}

49
src/main/java/com/fr/plugin/xxxx/saml/xxxx/saml/servlet/SAMLRequestServlet.java

@ -0,0 +1,49 @@
package com.fr.plugin.xxxx.saml.xxxx.saml.servlet;
import com.fr.plugin.xxxx.saml.xxxx.saml.SAMLException;
import com.fr.plugin.xxxx.saml.xxxx.saml.SAMLResponseValidator;
import com.fr.plugin.xxxx.saml.xxxx.saml.impl.SAMLRequestImpl;
import com.fr.plugin.xxxx.saml.xxxx.saml.impl.SAMLResponseValidatorImpl;
import org.apache.commons.codec.binary.Base64;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class SAMLRequestServlet extends HttpServlet{
private static final long serialVersionUID = 6599904768715487694L;
private static final String returnPage = "/WEB-INF/pages/index.jsp";
private static final String logon = "/WEB-INF/pages/logon.jsp";
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
byte[] req = new SAMLRequestImpl().generate().getBytes(StandardCharsets.UTF_8);
req = new Base64().encode(req);
request.setAttribute("SAMLRequest", new String(req,StandardCharsets.UTF_8));
} catch (SAMLException e) {
e.printStackTrace();
request.setAttribute("SAMLRequest", e.getMessage());
}
request.getRequestDispatcher(returnPage).forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException{
String resp = request.getParameter("SAMLResponse");
byte[] buffer = new Base64().decode(resp.getBytes(StandardCharsets.UTF_8));
try {
// System.out.println(new String(buffer,StandardCharsets.UTF_8));
SAMLResponseValidator vld = new SAMLResponseValidatorImpl(new String(buffer,StandardCharsets.UTF_8));
vld.validate();
request.setAttribute("uid", vld.getNameId());
} catch (SAMLException e) {
e.printStackTrace();
request.setAttribute("error", e.getMessage());
}
request.getRequestDispatcher(logon).forward(request, response);
}
}

132
src/main/java/com/fr/plugin/xxxx/saml/xxxx/security/AESUtil.java

@ -0,0 +1,132 @@
package com.fr.plugin.xxxx.saml.xxxx.security;
import com.huawei.secure.crypto.CommCryptUtil;
import com.huawei.secure.crypto.aes.AesCryptUtil;
import com.huawei.secure.crypto.rootkey.RootKeyCryptUtil;
import org.apache.commons.codec.DecoderException;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.util.Properties;
/**
* 实现AES加解密
*
*/
public class AESUtil {
private static AesConfigBean aesConfigBean;
static {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
InputStream is = null;
Properties properties = new Properties();
try {
is = cl.getResourceAsStream("saasclient.properties");
properties.load(is);
String workKey = properties.getProperty("aes.gcm.workKey");
String first = properties.getProperty("aes.gcm.first");
String second = properties.getProperty("aes.gcm.second");
String third = properties.getProperty("aes.gcm.third");
String salt = properties.getProperty("aes.gcm.salt");
aesConfigBean = new AesConfigBean();
aesConfigBean.setWorkKey(workKey);
aesConfigBean.setFirst(first);
aesConfigBean.setSecond(second);
aesConfigBean.setThird(third);
aesConfigBean.setSalt(salt);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
}
}
/**
* 设置根密钥
*/
public static void setRootKey() {
try {
if (CommCryptUtil.rootKey == null) {
RootKeyCryptUtil.getRootKey(aesConfigBean.getFirst(), aesConfigBean.getSecond(),
aesConfigBean.getThird(), aesConfigBean.getSalt());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* AES解密
*
* @param encryptString
* 加密后字符串
* @param workKey
* 工作秘钥
* @return
* @throws EncryptException
*/
private static String decrypt(String encryptString, String workKey) throws EncryptException {
String result = "";
try {
setRootKey();
result = AesCryptUtil.decryptByAesGcm(encryptString, workKey);
} catch (IOException | GeneralSecurityException | DecoderException e) {
throw new EncryptException(e.getMessage(), e);
}
return result;
}
/**
* AES解密
*
* @param encryptString
* 加密后字符串
* @return
* @throws EncryptException
*/
public static String decrypt(String encryptString) throws EncryptException {
return decrypt(encryptString, aesConfigBean.getWorkKey());
}
/**
* AES加密
*
* @param originalString
* 原字符串
* @param workKey
* 工作秘钥
* @return
* @throws EncryptException
*/
private static String encrypt(String originalString, String workKey) throws EncryptException {
String result = "";
try {
setRootKey();
result = AesCryptUtil.encryptByAesGcm(originalString, workKey);
} catch (IOException | GeneralSecurityException | DecoderException e) {
throw new EncryptException(e.getMessage(), e);
}
return result;
}
/**
* AES加密
*
* @param originalString
* 原字符串
* @return
* @throws EncryptException
*/
public static String encrypt(String originalString) throws EncryptException {
return encrypt(originalString, aesConfigBean.getWorkKey());
}
}

148
src/main/java/com/fr/plugin/xxxx/saml/xxxx/security/AESUtilBak.java

@ -0,0 +1,148 @@
package com.fr.plugin.xxxx.saml.xxxx.security;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Properties;
import java.util.UUID;
/**
* 实现AES加解密
*
*/
public class AESUtilBak {
private static final String ENCODING = "UTF-8";
private static final String KEY_ALGORITHM = "AES";
/**
* 加解密算法/工作模式/填充方式
*/
private static final String DEFAULT_CIPHER_ALGORITHM = "AES/CBC/PKCS5Padding";
/**
* 填充向量
*/
private static final String FILL_VECTOR = "977a51f2c27c026d";
/**
* AES密钥
*/
private static final String SECRET_KEY;
static {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
InputStream is = null;
Properties properties = new Properties();
try {
is = cl.getResourceAsStream("config/saasclient.properties");
properties.load(is);
SECRET_KEY = properties.getProperty("secretKey");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
}
}
/**
* 加密字符串
*
* @param content
* 字符串
* @param password
* 密钥KEY
* @return
* @throws EncryptException
* @throws Exception
*/
public static String encrypt(String content) throws EncryptException {
String password = byte2hex(SECRET_KEY.getBytes());
byte[] raw = hex2byte(password);
SecretKeySpec skeySpec = new SecretKeySpec(raw, KEY_ALGORITHM);
Cipher cipher = null;
try {
cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
IvParameterSpec iv = new IvParameterSpec(FILL_VECTOR.getBytes());
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] anslBytes = content.getBytes(ENCODING);
byte[] encrypted = cipher.doFinal(anslBytes);
return new String(new Base64().encode(encrypted),
StandardCharsets.UTF_8);
} catch (Exception e) {
throw new EncryptException(e.getMessage(), e);
}
}
/**
* 解密
*
* @param content
* 解密前的字符串
* @param password
* 解密KEY
* @return
* @throws Exception
* @author cdduqiang
* @throws EncryptException
* @date 2014年4月3日
*/
public static String decrypt(String content) throws EncryptException {
try {
String password = byte2hex(SECRET_KEY.getBytes());
byte[] raw = hex2byte(password);
SecretKeySpec skeySpec = new SecretKeySpec(raw, KEY_ALGORITHM);
Cipher cipher = Cipher.getInstance(DEFAULT_CIPHER_ALGORITHM);
IvParameterSpec iv = new IvParameterSpec(FILL_VECTOR.getBytes());
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] encrypted1 = new Base64().decode(content
.getBytes(StandardCharsets.UTF_8));
byte[] original = cipher.doFinal(encrypted1);
return new String(original, ENCODING);
} catch (Exception e) {
throw new EncryptException(e.getMessage(), e);
}
}
public static byte[] hex2byte(String strhex) {
if (strhex == null) {
return null;
}
int l = strhex.length();
if (l % 2 == 1) {
return null;
}
byte[] b = new byte[l / 2];
for (int i = 0; i != l / 2; i++) {
b[i] = (byte) Integer.parseInt(strhex.substring(i * 2, i * 2 + 2),
16);
}
return b;
}
public static String byte2hex(byte[] b) {
String hs = "";
String stmp = "";
for (int n = 0; n < b.length; n++) {
stmp = (Integer.toHexString(b[n] & 0XFF));
if (stmp.length() == 1) {
hs = hs + "0" + stmp;
} else {
hs = hs + stmp;
}
}
return hs;
}
}

78
src/main/java/com/fr/plugin/xxxx/saml/xxxx/security/AesConfigBean.java

@ -0,0 +1,78 @@
package com.fr.plugin.xxxx.saml.xxxx.security;
import java.io.Serializable;
/**
* AES配置对象
*
*/
public class AesConfigBean implements Serializable {
private static final long serialVersionUID = -3139888533298384987L;
/**
* 工作秘钥
*/
private String workKey;
/**
* 非加密根密钥分组一, 安全随机数生成至少16字节
*/
private String first;
/**
* 非加密根密钥分组二, 安全随机数生成至少16字节
*/
private String second;
/**
* 非加密根密钥分组三, 安全随机数生成至少16字节
*/
private String third;
/**
* 非加密盐值, 安全随机数生成至少16字节
*/
private String salt = "D81AB4FC090E01A344CD8831409F943E";
public String getWorkKey() {
return workKey;
}
public void setWorkKey(String workKey) {
this.workKey = workKey;
}
public String getFirst() {
return first;
}
public void setFirst(String first) {
this.first = first;
}
public String getSecond() {
return second;
}
public void setSecond(String second) {
this.second = second;
}
public String getThird() {
return third;
}
public void setThird(String third) {
this.third = third;
}
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
}

130
src/main/java/com/fr/plugin/xxxx/saml/xxxx/security/AesGcm.java

@ -0,0 +1,130 @@
package com.fr.plugin.xxxx.saml.xxxx.security;
import com.huawei.secure.crypto.CommCryptUtil;
import com.huawei.secure.crypto.aes.AesCryptUtil;
import com.huawei.secure.crypto.rootkey.RootKeyCryptUtil;
import org.apache.commons.codec.DecoderException;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.util.Properties;
public class AesGcm {
private static AesConfigBean aesConfigBean;
static {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
InputStream is = null;
Properties properties = new Properties();
try {
is = cl.getResourceAsStream("config/saasclient.properties");
properties.load(is);
String workKey = properties.getProperty("aes.gcm.workKey");
String first = properties.getProperty("aes.gcm.first");
String second = properties.getProperty("aes.gcm.second");
String third = properties.getProperty("aes.gcm.third");
String salt = properties.getProperty("aes.gcm.salt");
aesConfigBean = new AesConfigBean();
aesConfigBean.setWorkKey(workKey);
aesConfigBean.setFirst(first);
aesConfigBean.setSecond(second);
aesConfigBean.setThird(third);
aesConfigBean.setSalt(salt);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
}
}
/**
* 设置根密钥
*/
public static void setRootKey() {
try {
if (CommCryptUtil.rootKey == null) {
RootKeyCryptUtil.getRootKey(aesConfigBean.getFirst(),
aesConfigBean.getSecond(), aesConfigBean.getThird(),
aesConfigBean.getSalt());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* AES解密
*
* @param encryptString
* 加密后字符串
* @param workKey
* 工作秘钥
* @return
* @throws EncryptException
*/
private static String decrypt(String encryptString, String workKey)
throws EncryptException {
String result = "";
try {
setRootKey();
result = AesCryptUtil.decryptByAesGcm(encryptString, workKey);
} catch (IOException | GeneralSecurityException | DecoderException e) {
throw new EncryptException(e.getMessage(), e);
}
return result;
}
/**
* AES解密
*
* @param encryptString
* 加密后字符串
* @return
* @throws EncryptException
*/
public static String decrypt(String encryptString) throws EncryptException {
return decrypt(encryptString, aesConfigBean.getWorkKey());
}
/**
* AES加密
*
* @param originalString
* 原字符串
* @param workKey
* 工作秘钥
* @return
* @throws EncryptException
*/
private static String encrypt(String originalString, String workKey)
throws EncryptException {
String result = "";
try {
setRootKey();
result = AesCryptUtil.encryptByAesGcm(originalString, workKey);
} catch (IOException | GeneralSecurityException | DecoderException e) {
throw new EncryptException(e.getMessage(), e);
}
return result;
}
/**
* AES加密
*
* @param originalString
* 原字符串
* @return
* @throws EncryptException
*/
public static String encrypt(String originalString) throws EncryptException {
return encrypt(originalString, aesConfigBean.getWorkKey());
}
}

58
src/main/java/com/fr/plugin/xxxx/saml/xxxx/security/Encrypt.java

@ -0,0 +1,58 @@
package com.fr.plugin.xxxx.saml.xxxx.security;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public final class Encrypt {
private static final String strKey = "key4kerb";
public static String encryptWithDES(String strToEncrypt)
throws EncryptException {
SecretKey deskey = new SecretKeySpec(strKey.getBytes(StandardCharsets.UTF_8), "DES");;
try {
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, deskey);
byte[] bEncoded = cipher.doFinal(strToEncrypt.getBytes(StandardCharsets.UTF_8));
return new String(new Base64().encode(bEncoded),StandardCharsets.UTF_8);
} catch (NoSuchAlgorithmException e) {
throw new EncryptException(e.getMessage(),e);
} catch (NoSuchPaddingException e) {
throw new EncryptException(e.getMessage(),e);
} catch (InvalidKeyException e) {
throw new EncryptException(e.getMessage(),e);
} catch (IllegalBlockSizeException e) {
throw new EncryptException(e.getMessage(),e);
} catch (BadPaddingException e) {
throw new EncryptException(e.getMessage(),e);
}
}
public static String decryptWithDES(String strToDecrypt)
throws EncryptException {
SecretKey deskey = new SecretKeySpec(strKey.getBytes(StandardCharsets.UTF_8), "DES");
try {
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, deskey);
byte[] bEncodedDeB64ed = new Base64().decode(strToDecrypt.getBytes(StandardCharsets.UTF_8));
byte[] bDecoded = cipher.doFinal(bEncodedDeB64ed);
return new String(bDecoded,StandardCharsets.UTF_8);
} catch (NoSuchAlgorithmException e) {
throw new EncryptException(e.getMessage(),e);
} catch (NoSuchPaddingException e) {
throw new EncryptException(e.getMessage(),e);
} catch (InvalidKeyException e) {
throw new EncryptException(e.getMessage(),e);
} catch (IllegalBlockSizeException e) {
throw new EncryptException(e.getMessage(),e);
} catch (BadPaddingException e) {
throw new EncryptException(e.getMessage(),e);
}
}
}

20
src/main/java/com/fr/plugin/xxxx/saml/xxxx/security/EncryptException.java

@ -0,0 +1,20 @@
package com.fr.plugin.xxxx.saml.xxxx.security;
public class EncryptException extends Exception {
private static final long serialVersionUID = 7208167606845246287L;
public EncryptException() {
}
public EncryptException(String paramString) {
super(paramString);
}
public EncryptException(String paramString, Throwable paramThrowable) {
super(paramString, paramThrowable);
}
public EncryptException(Throwable paramThrowable) {
super(paramThrowable);
}
}

76
src/main/java/com/fr/plugin/xxxx/saml/xxxx/security/Test.java

@ -0,0 +1,76 @@
package com.fr.plugin.xxxx.saml.xxxx.security;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test {
// 加密
public static String Encrypt(String sSrc, String sKey) throws Exception {
if (sKey == null) {
System.out.print("Key为空null");
return null;
}
// 判断Key是否为16位
if (sKey.length() != 16) {
System.out.print("Key长度不是16位");
return null;
}
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128, new SecureRandom(sKey.getBytes()));
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");// "算法/模式/补码方式"
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
return new String(new Base64().encode(encrypted),StandardCharsets.UTF_8);// 此处使用BASE64做转码功能,同时能起到2次加密的作用。
}
public static String Decrypt(String sSrc, String sKey) throws Exception {
try {
// 判断Key是否正确
if (sKey == null) {
System.out.print("Key为空null");
return null;
}
// 判断Key是否为16位
if (sKey.length() != 16) {
System.out.print("Key长度不是16位");
return null;
}
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128, new SecureRandom(sKey.getBytes()));
SecretKey secretKey = kgen.generateKey();
byte[] enCodeFormat = secretKey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(enCodeFormat, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted1 = new Base64().decode(sSrc.getBytes(StandardCharsets.UTF_8));
try {
byte[] original = cipher.doFinal(encrypted1);
String originalString = new String(original, "utf-8");
return originalString;
} catch (Exception e) {
System.out.println(e.toString());
return null;
}
} catch (Exception ex) {
System.out.println(ex.toString());
return null;
}
}
}

16
src/main/resources/conf.properties

@ -0,0 +1,16 @@
##\u8FD4\u56DE\u9ED8\u8BA4\u767B\u5F55\u9875\u9762\u5730\u5740
return=http://www.baidu.com
##\u767B\u51FA\u5730\u5740,\u9700\u8981\u9644\u5E26\u4E0A\u540E\u9762\u9000\u51FA\u7684issuer\u53C2\u6570
logout=
#\u52A0\u5BC6\u79D8\u94A5
key=
##\u9ED8\u8BA4\u8D85\u65F6\u65F6\u95F4\uFF0C\u5355\u4F4D\u5206\u949F
timeout=5
##\u6570\u636E\u8FDE\u63A5
connection=
##cron
cron=0 0/5 * * * ? *

31
src/main/resources/saasclient.properties

@ -0,0 +1,31 @@
#Identity myself in saaslogin
issuer=http://xxxx:8080/samldemo/
#Submit SAML reponse to this URL.
serviceurl=http://xxxx:8080/samldemo/
#path to JKS file
keystore=config/saml/jks/HuaweiCA.jks
#password of key store.According to IT develop specification, password should be
#encrypted.Here we use DES algorithm to encrypt it.
storepassword=security:xxxx
#password of key store.According to IT develop specification, password should be
#encrypted.Here we use DES algorithm to encrypt it.
keypassword=security:xxxx
#alias of the keystore
keyalias=xxxx
#certificate file path.Form Huawei SSO team
certificatepath=xxxx
#Message digest, support SHA1, SHA256, SHA512 encryption algorithm, default SHA1
digestAlgorithm=SHA256
#Digital signature, support RSA_SHA1, RSA_SHA256, RSA_SHA512 encryption algorithm, default RSA_SHA1
signatureAlgorithm=RSA_SHA256
#AES\u5DE5\u4F5C\u79D8\u94A5
aes.gcm.workKey=security:xxxx
#AES\u975E\u52A0\u5BC6\u6839\u5BC6\u94A5\u5206\u7EC4\u4E00, \u5B89\u5168\u968F\u673A\u6570\u751F\u6210\uFF0C\u81F3\u5C1116\u5B57\u8282
aes.gcm.first=xxxx
#AES\u975E\u52A0\u5BC6\u6839\u5BC6\u94A5\u5206\u7EC4\u4E8C, \u5B89\u5168\u968F\u673A\u6570\u751F\u6210\uFF0C\u81F3\u5C1116\u5B57\u8282
aes.gcm.second=xxxx
#AES\u975E\u52A0\u5BC6\u6839\u5BC6\u94A5\u5206\u7EC4\u4E09, \u5B89\u5168\u968F\u673A\u6570\u751F\u6210\uFF0C\u81F3\u5C1116\u5B57\u8282
aes.gcm.third=xxxx
#AES\u975E\u52A0\u5BC6\u76D0\u503C, \u5B89\u5168\u968F\u673A\u6570\u751F\u6210\uFF0C\u81F3\u5C1116\u5B57\u8282
aes.gcm.salt=xxxx
Loading…
Cancel
Save