Skip to content

Commit

Permalink
代码优化
Browse files Browse the repository at this point in the history
  • Loading branch information
smthing committed Aug 18, 2024
1 parent d12c864 commit a0358e7
Show file tree
Hide file tree
Showing 12 changed files with 178 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.smartboot.socket.util.Attachment;
import tech.smartboot.servlet.conf.ServletInfo;
import tech.smartboot.servlet.conf.ServletMappingInfo;
import tech.smartboot.servlet.plugins.security.LoginAccount;

/**
* @author 三刀
Expand Down Expand Up @@ -42,4 +43,6 @@ public interface SmartHttpServletRequest extends HttpServletRequest {

void setAsyncSupported(boolean supported);

void setLoginAccount(LoginAccount loginAccount);

}
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ private void parseSecurityConstraint(WebAppInfo webAppInfo, Element parentElemen
Node webResourceCollection = Objects.requireNonNull(getChildNode(node, "web-resource-collection"));
// Map<String, List<String>> data = getNodeValues(webResourceCollection, Arrays.asList("web-resource-name", "url-pattern", "http-method"));
securityConstraint.getHttpMethods().addAll(getNodeValues(webResourceCollection, "http-method"));
securityConstraint.getHttpMethodOmissions().addAll(getNodeValues(webResourceCollection, "http-method-omission"));
getNodeValues(webResourceCollection, "url-pattern").forEach(urlPattern -> securityConstraint.getUrlPatterns().add(new UrlPattern(urlPattern)));
// securityConstraint.getResourceNames().addAll(getNodeValues(webResourceCollection, "web-resource-name"));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class SecurityConstraint {
// private final List<String> resourceNames = new ArrayList<>();
private final List<UrlPattern> urlPatterns = new ArrayList<>();
private final List<String> httpMethods = new ArrayList<>();
private final List<String> httpMethodOmissions = new ArrayList();

private List<String> roleNames;

Expand All @@ -32,6 +33,10 @@ public List<String> getHttpMethods() {
return httpMethods;
}

public List<String> getHttpMethodOmissions() {
return httpMethodOmissions;
}

public List<String> getRoleNames() {
return roleNames;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,73 +11,70 @@
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.UserTO;
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();
// UserTO userTO = null;
// if (!handlerContext.getServletInfo().getSecurityRoles().isEmpty()) {
// userTO = handlerContext.getServletContext().getRuntime().getSecurityProvider().getUser(request);
// if (userTO == null) {
// ((HttpServletResponse) handlerContext.getResponse()).sendError(403);
// return;
// }
// boolean valid = false;
// for (String role : handlerContext.getServletInfo().getSecurityRoles().values()) {
// if (userTO.getRoles().contains(role)) {
// valid = true;
// break;
// }
// }
// if (!valid) {
// ((HttpServletResponse) handlerContext.getResponse()).sendError(403);
// return;
// }
// }
List<SecurityConstraint> constraints = new ArrayList<>(handlerContext.getServletInfo().getSecurityConstraints());

List<SecurityConstraint> constraints = handlerContext.getServletInfo().getSecurityConstraints();
if (constraints.isEmpty()) {
constraints = handlerContext.getServletContext().getDeploymentInfo().getSecurityConstraints().stream().filter(securityConstraint -> {
for (UrlPattern urlPattern : securityConstraint.getUrlPatterns()) {
if (PathMatcherUtil.matches((HttpServletRequest) handlerContext.getRequest(), urlPattern)) {
return true;
}
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();
}
}
return false;
}).toList());
//不存在匹配的安全约束
if (constraints.isEmpty()) {
doNext(handlerContext);
return;
}
constraints = constraints.stream().filter(securityConstraint -> securityConstraint.getRoleNames() == null || securityConstraint.getHttpMethods().isEmpty() || securityConstraint.getHttpMethods().contains(request.getMethod())).toList();

constraints = constraints.stream().filter(securityConstraint -> ((CollectionUtils.isNotEmpty(securityConstraint.getRoleNames()) || securityConstraint.getEmptyRoleSemantic() == ServletSecurity.EmptyRoleSemantic.PERMIT)) && ((securityConstraint.getHttpMethods().isEmpty() || securityConstraint.getHttpMethods().contains(request.getMethod())) && !securityConstraint.getHttpMethodOmissions().contains(request.getMethod()))).toList();
if (constraints.isEmpty()) {
((HttpServletResponse) handlerContext.getResponse()).sendError(403);
return;
}
UserTO userTO = handlerContext.getServletContext().getRuntime().getSecurityProvider().getUser(request);
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 (userTO.getRoles().contains(role)) {
if (securityAccount.getRoles().contains(role)) {
loginAccount.getRoles().add(role);
return true;
}
}
return false;
}).toList();
if (constraints.isEmpty()) {
((HttpServletResponse) handlerContext.getResponse()).sendError(403);
((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 @@ -41,6 +41,8 @@
import tech.smartboot.servlet.conf.ServletInfo;
import tech.smartboot.servlet.conf.ServletMappingInfo;
import tech.smartboot.servlet.impl.fileupload.SmartHttpRequestContext;
import tech.smartboot.servlet.plugins.security.LoginAccount;
import tech.smartboot.servlet.plugins.security.SecurityAccount;
import tech.smartboot.servlet.provider.SessionProvider;
import tech.smartboot.servlet.third.commons.fileupload.FileItem;
import tech.smartboot.servlet.third.commons.fileupload.FileUpload;
Expand Down Expand Up @@ -116,6 +118,7 @@ public class HttpServletRequestImpl implements SmartHttpServletRequest {
private final CompletableFuture<Object> completableFuture;

private ServletMappingInfo servletMappingInfo;
private LoginAccount principal;

public HttpServletRequestImpl(HttpRequest request, ServletContextRuntime runtime, CompletableFuture<Object> completableFuture) {
this.request = request;
Expand Down Expand Up @@ -251,12 +254,19 @@ public String getRemoteUser() {

@Override
public boolean isUserInRole(String role) {
throw new UnsupportedOperationException();
return runtime.getSecurityProvider().isUserInRole(role, principal, this);
}

@Override
public Principal getUserPrincipal() {
return null;
if (principal == null) {
// try {
// principal = runtime.getSecurityProvider().getUser(this);
// } catch (ServletException e) {
// throw new RuntimeException(e);
// }
}
return principal;
}

@Override
Expand Down Expand Up @@ -378,7 +388,10 @@ public boolean authenticate(HttpServletResponse response) {

@Override
public void login(String username, String password) throws ServletException {
throw new ServletException("Not Implemented");
SecurityAccount securityAccount = runtime.getSecurityProvider().login(username, password);
if (securityAccount != null) {
principal = new LoginAccount(securityAccount.getUsername(), securityAccount.getPassword(), securityAccount.getRoles());
}
}

@Override
Expand Down Expand Up @@ -826,6 +839,11 @@ public void setAsyncSupported(boolean supported) {
this.asyncSupported = asyncStarted;
}

@Override
public void setLoginAccount(LoginAccount loginAccount) {
this.principal = loginAccount;
}

@Override
public AsyncContext getAsyncContext() {
if (isAsyncStarted()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import tech.smartboot.servlet.conf.ServletMappingInfo;
import tech.smartboot.servlet.impl.HttpServletMappingImpl;
import tech.smartboot.servlet.impl.HttpServletRequestImpl;
import tech.smartboot.servlet.plugins.security.LoginAccount;

import java.util.Collections;
import java.util.Enumeration;
Expand Down Expand Up @@ -167,6 +168,11 @@ public void setAsyncSupported(boolean supported) {
this.request.setAsyncSupported(supported);
}

@Override
public void setLoginAccount(LoginAccount loginAccount) {
this.request.setLoginAccount(loginAccount);
}


@Override
public HttpServletMapping getHttpServletMapping() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,31 @@

package tech.smartboot.servlet.plugins.security;

import java.security.Principal;
import java.util.Set;

public class UserTO {
private String username;
private String password;
private Set<String> roles;
public class LoginAccount implements Principal {
private final String username;
private final String password;
private final Set<String> roles;

public UserTO(String username, String password, Set<String> roles) {
public LoginAccount(String username, String password, Set<String> roles) {
this.username = username;
this.password = password;
this.roles = roles;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public Set<String> getRoles() {
return roles;
}

public void setRoles(Set<String> roles) {
this.roles = roles;
@Override
public String getName() {
return username;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (C) [2022] smartboot [zhengjunweimail@163.com]
*
* 企业用户未经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.plugins.security;

import java.util.Collections;
import java.util.Set;

/**
* 当前容器配置的认证信息
*
* @author 三刀
*/
public class SecurityAccount {
public static final String AUTH_TYPE_BASIC = "BASIC";
public static final String FORM = "FORM";
public static final String DIGEST = "DIGEST";
public static final String CLIENT_CERT = "CLIENT_CERT";
public static final String NONE = "NONE";
private final String username;
private final String password;
private final String authType;
private final Set<String> roles;

public SecurityAccount(String username, String password, String authType, Set<String> roles) {
this.username = username;
this.password = password;
this.authType = authType;
this.roles = Collections.unmodifiableSet(roles);
}

public String getUsername() {
return username;
}

public String getPassword() {
return password;
}

public Set<String> getRoles() {
return roles;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* Copyright (C) [2022] smartboot [zhengjunweimail@163.com]
*
* 企业用户未经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.plugins.security;

import tech.smartboot.servlet.Container;
import tech.smartboot.servlet.plugins.Plugin;

public class SecurityPlugin extends Plugin {
@Override
protected void initPlugin(Container container) {
super.initPlugin(container);
}
}
Loading

0 comments on commit a0358e7

Please sign in to comment.