LAPTOP-SB56SG4Q\86185
3 years ago
56 changed files with 4486 additions and 1 deletions
@ -1,3 +1,6 @@
|
||||
# open-JSD-7610 |
||||
|
||||
JSD-7610 SAML单点 |
||||
JSD-7610 SAML单点\ |
||||
免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ |
||||
仅作为开发者学习参考使用!禁止用于任何商业用途!\ |
||||
为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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> |
@ -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"); |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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); |
||||
} |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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)); |
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
@ -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; |
||||
} |
||||
|
||||
|
||||
} |
@ -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); |
||||
} |
||||
} |
@ -0,0 +1,5 @@
|
||||
package com.fr.plugin.xxxx.saml.xxxx.saml; |
||||
|
||||
public interface SAMLRequest { |
||||
public String generate() throws SAMLException; |
||||
} |
@ -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(); |
||||
} |
@ -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(); |
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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(); |
||||
} |
@ -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; |
||||
} |
||||
|
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
@ -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"; |
||||
} |
@ -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() { |
||||
} |
||||
} |
@ -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() { |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
@ -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());
|
||||
// }
|
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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()); |
||||
} |
||||
|
||||
|
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
@ -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()); |
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
||||
} |
||||
|
||||
|
||||
} |
@ -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); |
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
|
||||
|
||||
} |
@ -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 * * * ? * |
@ -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…
Reference in new issue