diff --git a/src/main/java/com/github/zxbu/webdavteambition/WebdavTeambitionApplication.java b/src/main/java/com/github/zxbu/webdavteambition/WebdavTeambitionApplication.java index 758ccee..0f8a0cd 100644 --- a/src/main/java/com/github/zxbu/webdavteambition/WebdavTeambitionApplication.java +++ b/src/main/java/com/github/zxbu/webdavteambition/WebdavTeambitionApplication.java @@ -40,4 +40,5 @@ public class WebdavTeambitionApplication { return filterRegistrationBean; } + } diff --git a/src/main/java/com/github/zxbu/webdavteambition/config/EmbeddedTomcatConfig.java b/src/main/java/com/github/zxbu/webdavteambition/config/EmbeddedTomcatConfig.java new file mode 100644 index 0000000..634c419 --- /dev/null +++ b/src/main/java/com/github/zxbu/webdavteambition/config/EmbeddedTomcatConfig.java @@ -0,0 +1,73 @@ +package com.github.zxbu.webdavteambition.config; + +import org.apache.catalina.authenticator.DigestAuthenticator; +import org.apache.catalina.core.StandardContext; +import org.apache.catalina.realm.GenericPrincipal; +import org.apache.catalina.realm.MessageDigestCredentialHandler; +import org.apache.catalina.realm.RealmBase; +import org.apache.tomcat.util.descriptor.web.SecurityCollection; +import org.apache.tomcat.util.descriptor.web.SecurityConstraint; +import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory; +import org.springframework.boot.web.server.WebServerFactoryCustomizer; +import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; +import org.springframework.core.Ordered; +import org.springframework.stereotype.Component; + +import java.security.Principal; +import java.util.Collections; + +@Component +public class EmbeddedTomcatConfig implements WebServerFactoryCustomizer, Ordered { + + @Override + public void customize(ConfigurableServletWebServerFactory factory) { + + TomcatServletWebServerFactory tomcatServletWebServerFactory = (TomcatServletWebServerFactory) factory; + + tomcatServletWebServerFactory.addContextCustomizers(context -> { + + RealmBase realm = new RealmBase() { + @Override + protected String getPassword(String username) { + return "12345"; + } + + @Override + protected Principal getPrincipal(String username) { + return new GenericPrincipal(username, "12345", Collections.singletonList("*")); + } + }; + + MessageDigestCredentialHandler credentialHandler = new MessageDigestCredentialHandler(); +// try { +// credentialHandler.setAlgorithm("md5"); +// } catch (NoSuchAlgorithmException e) { +// e.printStackTrace(); +// } + realm.setCredentialHandler(credentialHandler); + + context.setRealm(realm); + DigestAuthenticator valve = new DigestAuthenticator(); + SecurityConstraint securityConstraint = new SecurityConstraint(); + securityConstraint.setAuthConstraint(true); + securityConstraint.addAuthRole("*"); +// securityConstraint.setUserConstraint("CONFIDENTIAL"); + SecurityCollection collection = new SecurityCollection(); + collection.addPattern("/*"); + securityConstraint.addCollection(collection); + + context.addConstraint(securityConstraint); + + StandardContext standardContext = (StandardContext) context; + + + context.getPipeline().addValve(valve); + }); + + } + + @Override + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/zxbu/webdavteambition/filter/ErrorFilter.java b/src/main/java/com/github/zxbu/webdavteambition/filter/ErrorFilter.java index 9ed6132..ef9259a 100644 --- a/src/main/java/com/github/zxbu/webdavteambition/filter/ErrorFilter.java +++ b/src/main/java/com/github/zxbu/webdavteambition/filter/ErrorFilter.java @@ -1,5 +1,8 @@ package com.github.zxbu.webdavteambition.filter; +import net.sf.webdav.WebdavStatus; +import org.apache.tomcat.util.http.fileupload.IOUtils; +import org.springframework.core.io.ClassPathResource; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; @@ -9,10 +12,24 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import java.io.IOException; +import java.io.InputStream; import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; public class ErrorFilter extends OncePerRequestFilter { + private static final String errorPage = readErrorPage(); + private static String readErrorPage() { + try { + ClassPathResource classPathResource = new ClassPathResource("error.xml"); + InputStream inputStream = classPathResource.getInputStream(); + byte[] buffer = new byte[(int) classPathResource.contentLength()]; + IOUtils.readFully(inputStream, buffer); + return new String(buffer, StandardCharsets.UTF_8); + } catch (IOException e) { + return ""; + } + } @Override protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { @@ -21,10 +38,19 @@ public class ErrorFilter extends OncePerRequestFilter { try { filterChain.doFilter(httpServletRequest, wrapperResponse); if (wrapperResponse.hasErrorToSend()) { - httpServletResponse.setStatus(wrapperResponse.getStatus()); - if (wrapperResponse.getMessage() != null) { - httpServletResponse.getWriter().write(wrapperResponse.getMessage()); + int status = wrapperResponse.getStatus(); + if (status == 401) { +// httpServletResponse.addHeader("WWW-Authenticate", "Digest realm=\"iptel.org\", qop=\"auth,auth-int\",\n" + +// "nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", opaque=\"\", algorithm=MD5"); +// + } + httpServletResponse.setStatus(status); + String message = wrapperResponse.getMessage(); + if (message == null) { + message = WebdavStatus.getStatusText(status); } + String errorXml = errorPage.replace("{{code}}", status + "").replace("{{message}}", message); + httpServletResponse.getWriter().write(errorXml); } httpServletResponse.flushBuffer(); } catch (Throwable t) { diff --git a/src/main/java/com/github/zxbu/webdavteambition/store/AliYunDriverFileSystemStore.java b/src/main/java/com/github/zxbu/webdavteambition/store/AliYunDriverFileSystemStore.java index 6d8c113..70379a3 100644 --- a/src/main/java/com/github/zxbu/webdavteambition/store/AliYunDriverFileSystemStore.java +++ b/src/main/java/com/github/zxbu/webdavteambition/store/AliYunDriverFileSystemStore.java @@ -3,10 +3,8 @@ package com.github.zxbu.webdavteambition.store; import com.github.zxbu.webdavteambition.model.FileType; import com.github.zxbu.webdavteambition.model.PathInfo; import com.github.zxbu.webdavteambition.model.result.TFile; -import net.sf.webdav.ITransaction; -import net.sf.webdav.IWebdavStore; -import net.sf.webdav.StoredObject; -import net.sf.webdav.Transaction; +import net.sf.webdav.*; +import net.sf.webdav.exceptions.UnauthenticatedException; import net.sf.webdav.exceptions.WebdavException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -17,6 +15,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.security.Principal; +import java.util.Enumeration; import java.util.Set; public class AliYunDriverFileSystemStore implements IWebdavStore { @@ -43,6 +42,17 @@ public class AliYunDriverFileSystemStore implements IWebdavStore { @Override public ITransaction begin(Principal principal, HttpServletRequest req, HttpServletResponse resp) { LOGGER.debug("begin"); + Enumeration headerNames = req.getHeaderNames(); + System.out.println(req.getMethod() + " " + req.getRequestURI()); + System.out.println("principal:" + principal); + while (headerNames.hasMoreElements()) { + String s = headerNames.nextElement(); + System.out.println(s + ":" + req.getHeader(s)); + } + + + System.out.println("-----------------------"); + System.out.println(); aliYunDriverClientService.clearCache(); return new Transaction(principal, req, resp); @@ -51,9 +61,10 @@ public class AliYunDriverFileSystemStore implements IWebdavStore { @Override public void checkAuthentication(ITransaction transaction) { LOGGER.debug("checkAuthentication"); -// if (transaction.getPrincipal() == null) { -// throw new UnauthenticatedException(WebdavStatus.SC_UNAUTHORIZED); -// } + HttpServletRequest req = transaction.getRequest(); + if (transaction.getPrincipal() == null) { + throw new UnauthenticatedException(WebdavStatus.SC_UNAUTHORIZED); + } } @Override diff --git a/src/main/java/net/sf/webdav/WebDavServletBean.java b/src/main/java/net/sf/webdav/WebDavServletBean.java index dacfaaa..d1f32ea 100644 --- a/src/main/java/net/sf/webdav/WebDavServletBean.java +++ b/src/main/java/net/sf/webdav/WebDavServletBean.java @@ -109,6 +109,10 @@ public class WebDavServletBean extends HttpServlet { if (LOG.isTraceEnabled()) debugRequest(methodName, req); + if (returnError(req, resp)) { + return; + } + try { Principal userPrincipal = getUserPrincipal(req); transaction = _store.begin(userPrincipal, req, resp); @@ -171,15 +175,32 @@ public class WebDavServletBean extends HttpServlet { } /** - * Method that permit to customize the way + * Method that permit to customize the way * user information are extracted from the request, default use JAAS + * * @param req * @return */ protected Principal getUserPrincipal(HttpServletRequest req) { - return req.getUserPrincipal(); + return req.getUserPrincipal(); } - + + private boolean returnError(HttpServletRequest req, HttpServletResponse resp) throws IOException { + if (req.getRequestURI().equals("/error")) { + Object codeObject = req.getAttribute("javax.servlet.error.status_code"); + if (codeObject != null) { + int code = Integer.parseInt(codeObject.toString()); + if (code > 400) { + resp.setStatus(code); + resp.flushBuffer(); + return true; + } + } + } + return false; + } + + private void debugRequest(String methodName, HttpServletRequest req) { LOG.trace("-----------"); LOG.trace("WebdavServlet\n request: methodName = " + methodName); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index cf6f6e3..b7eeb0d 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,3 +1,3 @@ -#logging.level.net.sf.webdav=trace +logging.level.net.sf.webdav=trace logging.file.path=/var/log/ -logging.file.name=webdav.log \ No newline at end of file +logging.file.name=webdav.log