Skip to content

Commit

Permalink
代码优化
Browse files Browse the repository at this point in the history
  • Loading branch information
smthing committed Aug 19, 2024
1 parent b7b61f5 commit 9ef1693
Show file tree
Hide file tree
Showing 17 changed files with 382 additions and 83 deletions.
6 changes: 6 additions & 0 deletions servlet-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@
<artifactId>jakarta.websocket-client-api</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.mortbay.jasper</groupId>
<artifactId>apache-jsp</artifactId>
<version>10.1.5</version>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,10 @@ private ServletContextRuntime getServletRuntime(String localPath, String context
DeploymentInfo deploymentInfo = servletRuntime.getDeploymentInfo();
//set session timeout
deploymentInfo.setSessionTimeout(webAppInfo.getSessionTimeout());
deploymentInfo.setLoginConfig(webAppInfo.getLoginConfig());
// if (webAppInfo.getLoginConfig() != null && webAppInfo.getLoginConfig().getLoginPage().endsWith(".jsp")) {
// servletRuntime.getServletContext().addJspFile("aaaaaa", webAppInfo.getLoginConfig().getLoginPage());
// }
//register Servlet into deploymentInfo
webAppInfo.getServletMappings().forEach(deploymentInfo::addServletMapping);
webAppInfo.getServlets().values().forEach(deploymentInfo::addServlet);
Expand Down Expand Up @@ -458,7 +462,7 @@ private ServletContextRuntime getServletRuntime(String localPath, String context
deploymentInfo.setWelcomeFiles(welcomeFiles);
}

servletRuntime.getSecurityProvider().init(webAppInfo.getSecurityConstraints());
servletRuntime.getSecurityProvider().init(webAppInfo.getSecurityConstraints(),webAppInfo.getLoginConfig());
return servletRuntime;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import tech.smartboot.servlet.impl.ServletContextImpl;
import tech.smartboot.servlet.impl.ServletContextWrapperListener;
import tech.smartboot.servlet.plugins.Plugin;
import tech.smartboot.servlet.plugins.security.SecurityCheckServlet;
import tech.smartboot.servlet.plugins.security.SecurityProviderImpl;
import tech.smartboot.servlet.provider.AsyncContextProvider;
import tech.smartboot.servlet.provider.DispatcherProvider;
Expand Down Expand Up @@ -196,6 +197,16 @@ private void newServletsInstance(DeploymentInfo deploymentInfo) throws Instantia
deploymentInfo.addServletMapping(new ServletMappingInfo(ServletInfo.DEFAULT_SERVLET_NAME, "/"));
}

if (deploymentInfo.getServletMappings().stream().noneMatch(mapping -> mapping.getUrlPattern().equals("/j_security_check"))) {
ServletInfo servletInfo = new ServletInfo();
servletInfo.setServletName("SecurityCheckServlet");
servletInfo.setServlet(new SecurityCheckServlet(deploymentInfo));
servletInfo.setDynamic(true);
servletInfo.setLoadOnStartup(1);
deploymentInfo.addServlet(servletInfo);
deploymentInfo.addServletMapping(new ServletMappingInfo(servletInfo.getServletName(), "/j_security_check"));
}


}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public interface SmartHttpServletRequest extends HttpServletRequest {

void setServletInfo(ServletInfo servletInfo);

ServletInfo getServletInfo();

/**
* 获取附件对象
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import tech.smartboot.servlet.conf.ErrorPageInfo;
import tech.smartboot.servlet.conf.FilterInfo;
import tech.smartboot.servlet.conf.FilterMappingInfo;
import tech.smartboot.servlet.conf.LoginConfig;
import tech.smartboot.servlet.conf.OrderMeta;
import tech.smartboot.servlet.conf.SecurityConstraint;
import tech.smartboot.servlet.conf.ServletInfo;
Expand Down Expand Up @@ -122,9 +123,30 @@ private Element commonParse(WebAppInfo webAppInfo, InputStream contextFile) thro
parseSecurityConstraint(webAppInfo, parentElement);

parseAbsoluteOrdering(webAppInfo, parentElement);

parseLoginConfig(webAppInfo, parentElement);
return parentElement;
}

private void parseLoginConfig(WebAppInfo webAppInfo, Element parentElement) {
Node node = getChildNode(parentElement, "login-config");
if (node == null) {
return;
}
Map<String, String> nodeValues = getNodeValue(node, List.of("realm-name"));
LoginConfig loginConfig = new LoginConfig();
loginConfig.setRealmName(nodeValues.get("realm-name"));
Node formLoginConfig = getChildNode(node, "form-login-config");
if (formLoginConfig != null) {
nodeValues = getNodeValue(formLoginConfig, List.of("form-login-page", "form-error-page"));
loginConfig.setErrorPage(nodeValues.get("form-error-page"));
loginConfig.setLoginPage(nodeValues.get("form-login-page"));
}
Map<String, String> authMethod = getNodeValue(node, List.of("auth-method"));
loginConfig.setAuthMethod(authMethod.get("auth-method"));
webAppInfo.setLoginConfig(loginConfig);
}

private void parseBasicInfo(WebAppInfo webAppInfo, Element parentElement) {
Map<String, String> map = getNodeValue(parentElement, Arrays.asList("display-name", "description"));
if (map.containsKey("display-name")) {
Expand Down Expand Up @@ -313,7 +335,12 @@ private void parseServletMapping(WebAppInfo webAppInfo, Element parentElement) {
for (Node node : childNodeList) {
Map<String, String> nodeData = getNodeValue(node, Collections.singletonList("servlet-name"));
String servletName = nodeData.get("servlet-name");
getNodeValues(node, "url-pattern").forEach(urlPattern -> webAppInfo.getServletMappings().add(new ServletMappingInfo(servletName, urlPattern)));
getNodeValues(node, "url-pattern").forEach(urlPattern -> {
ServletMappingInfo servletMappingInfo = new ServletMappingInfo(servletName, urlPattern);
if (servletMappingInfo.getMappingMatch() != null) {
webAppInfo.getServletMappings().add(servletMappingInfo);
}
});
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public class DeploymentInfo {
* 会话超时时间
*/
private int sessionTimeout;

private LoginConfig loginConfig;
private final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

public URL getContextUrl() {
Expand Down Expand Up @@ -177,6 +177,14 @@ public void addFilter(final FilterInfo filter) {
filters.put(filter.getFilterName(), filter);
}

public LoginConfig getLoginConfig() {
return loginConfig;
}

public void setLoginConfig(LoginConfig loginConfig) {
this.loginConfig = loginConfig;
}

public void amazing() {
if (servletContainerInitializers.isEmpty()) {
servletContainerInitializers = Collections.emptyList();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (C) [2022] smartboot [[email protected]]
*
* 企业用户未经smartboot组织特别许可,需遵循AGPL-3.0开源协议合理合法使用本项目。
*
* Enterprise users are required to use this project reasonably
* and legally in accordance with the AGPL-3.0 open source agreement
* without special permission from the smartboot organization.
*/

package tech.smartboot.servlet.conf;

public class LoginConfig {
private String authMethod;
private String realmName;
private String loginPage;
private String errorPage;

public String getRealmName() {
return realmName;
}

public void setRealmName(String realmName) {
this.realmName = realmName;
}

public String getLoginPage() {
return loginPage;
}

public void setLoginPage(String loginPage) {
this.loginPage = loginPage;
}

public String getErrorPage() {
return errorPage;
}

public void setErrorPage(String errorPage) {
this.errorPage = errorPage;
}

public String getAuthMethod() {
return authMethod;
}

public void setAuthMethod(String authMethod) {
this.authMethod = authMethod;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public class WebAppInfo {
private final List<SecurityConstraint> securityConstraints = new ArrayList<>();
private List<String> absoluteOrdering;
private boolean absoluteOrderingOther = false;
private LoginConfig loginConfig;

private int sessionTimeout = 0;

Expand Down Expand Up @@ -181,4 +182,12 @@ public List<FilterMappingInfo> getFilterMappingInfos() {
public List<ServletMappingInfo> getServletMappings() {
return servletMappings;
}

public LoginConfig getLoginConfig() {
return loginConfig;
}

public void setLoginConfig(LoginConfig loginConfig) {
this.loginConfig = loginConfig;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,79 +11,80 @@
package tech.smartboot.servlet.handler;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.ServletSecurity;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.smartboot.http.common.enums.HttpStatus;
import tech.smartboot.servlet.conf.SecurityConstraint;
import tech.smartboot.servlet.conf.UrlPattern;
import tech.smartboot.servlet.plugins.security.LoginAccount;
import tech.smartboot.servlet.plugins.security.SecurityAccount;
import tech.smartboot.servlet.util.CollectionUtils;
import tech.smartboot.servlet.util.PathMatcherUtil;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

public class SecurityHandler extends Handler {
@Override
public void handleRequest(HandlerContext handlerContext) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) handlerContext.getRequest();
List<SecurityConstraint> constraints = new ArrayList<>(handlerContext.getServletInfo().getSecurityConstraints());

constraints.addAll(handlerContext.getServletContext().getDeploymentInfo().getSecurityConstraints().stream().filter(securityConstraint -> {
for (UrlPattern urlPattern : securityConstraint.getUrlPatterns()) {
if (PathMatcherUtil.matches((HttpServletRequest) handlerContext.getRequest(), urlPattern)) {
return true;
}
}
return false;
}).toList());
//移除不匹配的httpMethod
constraints = constraints.stream().filter(securityConstraint -> !securityConstraint.getHttpMethodOmissions().contains(request.getMethod())).toList();
//不存在匹配的安全约束
if (constraints.isEmpty()) {
if (handlerContext.getServletContext().getRuntime().getSecurityProvider().login(handlerContext.getOriginalRequest(), (HttpServletResponse) handlerContext.getResponse(), handlerContext.getServletInfo())) {
doNext(handlerContext);
return;
}


constraints = constraints.stream().filter(securityConstraint -> (
//存在角色或者为PERMIT
(CollectionUtils.isNotEmpty(securityConstraint.getRoleNames()) || securityConstraint.getEmptyRoleSemantic() == ServletSecurity.EmptyRoleSemantic.PERMIT))
//为配置httpMethod,或者包含指定method
&& (securityConstraint.getHttpMethods().isEmpty() || securityConstraint.getHttpMethods().contains(request.getMethod())))
.toList();
if (constraints.isEmpty()) {
((HttpServletResponse) handlerContext.getResponse()).sendError(403);
return;
}
SecurityAccount securityAccount = handlerContext.getServletContext().getRuntime().getSecurityProvider().login(request);
if (securityAccount == null) {
((HttpServletResponse) handlerContext.getResponse()).sendError(HttpStatus.UNAUTHORIZED.value());
return;
}
LoginAccount loginAccount = new LoginAccount(securityAccount.getUsername(), securityAccount.getPassword(), new HashSet<>());
constraints = constraints.stream().filter(securityConstraint -> {
if (securityConstraint.getEmptyRoleSemantic() == ServletSecurity.EmptyRoleSemantic.PERMIT && CollectionUtils.isEmpty(securityConstraint.getRoleNames())) {
return true;
}
for (String role : securityConstraint.getRoleNames()) {
if (securityAccount.getRoles().contains(role)) {
//匹配的角色
loginAccount.getRoles().add(role);
return true;
}
}
return false;
}).toList();
if (constraints.isEmpty()) {
((HttpServletResponse) handlerContext.getResponse()).sendError(HttpStatus.FORBIDDEN.value());
return;
}
handlerContext.getOriginalRequest().setLoginAccount(loginAccount);
doNext(handlerContext);
// List<SecurityConstraint> constraints = new ArrayList<>(handlerContext.getServletInfo().getSecurityConstraints());
//
// constraints.addAll(handlerContext.getServletContext().getDeploymentInfo().getSecurityConstraints().stream().filter(securityConstraint -> {
// for (UrlPattern urlPattern : securityConstraint.getUrlPatterns()) {
// if (PathMatcherUtil.matches((HttpServletRequest) handlerContext.getRequest(), urlPattern)) {
// return true;
// }
// }
// return false;
// }).toList());
// //移除不匹配的httpMethod
// constraints = constraints.stream().filter(securityConstraint -> !securityConstraint.getHttpMethodOmissions().contains(request.getMethod())).toList();
// //不存在匹配的安全约束
// if (constraints.isEmpty()) {
// doNext(handlerContext);
// return;
// }
//
// //所有约束的角色为空,且为PERMIT
// if (constraints.stream().filter(securityConstraint -> CollectionUtils.isEmpty(securityConstraint.getRoleNames()) && securityConstraint.getEmptyRoleSemantic() == ServletSecurity.EmptyRoleSemantic.PERMIT).count() == constraints.size()) {
// doNext(handlerContext);
// return;
// }
//
// constraints = constraints.stream().filter(securityConstraint -> (
// //存在角色或者为PERMIT
// (CollectionUtils.isNotEmpty(securityConstraint.getRoleNames()) || securityConstraint.getEmptyRoleSemantic() == ServletSecurity.EmptyRoleSemantic.PERMIT))
// //为配置httpMethod,或者包含指定method
// && (securityConstraint.getHttpMethods().isEmpty() || securityConstraint.getHttpMethods().contains(request.getMethod()))).toList();
// if (constraints.isEmpty()) {
// ((HttpServletResponse) handlerContext.getResponse()).sendError(403);
// return;
// }
// SecurityAccount securityAccount = handlerContext.getServletContext().getRuntime().getSecurityProvider().login(request);
// if (securityAccount == null) {
// LoginConfig loginConfig = handlerContext.getServletContext().getDeploymentInfo().getLoginConfig();
// if (loginConfig != null && loginConfig.getLoginPage() != null) {
//// ((HttpServletResponse) handlerContext.getResponse()).sendRedirect(request.getContextPath() + loginConfig.getLoginPage());
// request.getSession().setAttribute("redirect", request.getRequestURI() + "?" + request.getQueryString());
// request.getRequestDispatcher(loginConfig.getLoginPage()).forward(request, handlerContext.getResponse());
// } else {
// ((HttpServletResponse) handlerContext.getResponse()).sendError(HttpStatus.UNAUTHORIZED.value());
// }
// return;
// }
// LoginAccount loginAccount = new LoginAccount(securityAccount.getUsername(), securityAccount.getPassword(), new HashSet<>());
// constraints = constraints.stream().filter(securityConstraint -> {
// if (securityConstraint.getEmptyRoleSemantic() == ServletSecurity.EmptyRoleSemantic.PERMIT && CollectionUtils.isEmpty(securityConstraint.getRoleNames())) {
// return true;
// }
// for (String role : securityConstraint.getRoleNames()) {
// if (securityAccount.getRoles().contains(role)) {
// //匹配的角色
// loginAccount.getRoles().add(role);
// return true;
// }
// }
// return false;
// }).toList();
// if (constraints.isEmpty()) {
// ((HttpServletResponse) handlerContext.getResponse()).sendError(HttpStatus.FORBIDDEN.value());
// return;
// }
// handlerContext.getOriginalRequest().setLoginAccount(loginAccount);
// doNext(handlerContext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,11 @@ public void setServletInfo(ServletInfo servletInfo) {
}
}

@Override
public ServletInfo getServletInfo() {
return servletInfo;
}

@Override
public Attachment getAttachment() {
return request.getAttachment();
Expand Down Expand Up @@ -383,7 +388,7 @@ public boolean isRequestedSessionIdFromURL() {

@Override
public boolean authenticate(HttpServletResponse response) {
throw new UnsupportedOperationException();
return principal != null;
}

@Override
Expand Down
Loading

0 comments on commit 9ef1693

Please sign in to comment.