使用基本身份验证集成 Servlet 安全性

问题描述 投票:0回答:1

我需要公开其余的 api,我们当前正在使用 servlet。不需要前端来测试我们的 api,我们只使用 postman 来测试端点。除了基本的身份验证安全性之外,我的获取和删除 api 映射工作正常。我在谷歌中找到了与我的要求相关的参考,当我在邮递员中选择基本身份验证时,它不起作用,它没有调用 RestAuthenticationFilter 方法。这是我的代码:

public class RestAuthenticationFilter implements Filter {
      public static final String AUTHENTICATION_HEADER = "Authorization";

      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
          throws IOException, ServletException {
          System.out.println("Filter");
        if (request instanceof HttpServletRequest) {
          final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
          final String authCredentials = httpServletRequest.getHeader(AUTHENTICATION_HEADER);
          System.out.println("authCredentials: "+authCredentials);

          final AuthService authService = new AuthService();
          final boolean authenticationStatus = authService.authenticate(authCredentials);
          System.out.println("authenticationStatus: "+authenticationStatus);
          if (authenticationStatus) {
            chain.doFilter(request, response);
          } else {
            if (response instanceof HttpServletResponse) {
              HttpServletResponse httpServletResponse = (HttpServletResponse) response;
              httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            }
          }
        }
      }

      public void init(FilterConfig filterConfig) throws ServletException {
        // No Implementation
      }

      public void destroy() {
        // No Implementation
      }
}

添加服务

public class AuthService {
      public boolean authenticate(final String authCredentials) {
         System.out.println("autservice");
        if (null == authCredentials) {
          return false;
        }

        // Header value format for Basic authentication will be "Basic encodedstring"
        final String encodedUserAuthCredentials = authCredentials.replaceFirst("Basic ", "");
        System.out.println("encodedUserAuthCredentials: "+encodedUserAuthCredentials);
        String decodedUserAuthCredentials = null;
        try {
//          sun.misc.BASE64Decoder dec = new sun.misc.BASE64Decoder();
//          String userpassDecoded = new String(dec.decodeBuffer(encodedUserAuthCredentials));
//          String base64String = BaseEncoding.base64().encode(encodedUserAuthCredentials.getBytes("UTF-8"));
//          byte[] decodedBytes = Base64.getDecoder().decode(encodedUserAuthCredentials);
//          decodedUserAuthCredentials = base64String;
            decodedUserAuthCredentials = DatatypeConverter.printBase64Binary(("admin:admin").getBytes("UTF-8"));
//          System.out.println("base64String: "+base64String);
            System.out.println("decodedUserAuthCredentials: "+decodedUserAuthCredentials);
        } catch (IOException e) {
          System.out.println("LOGGER");
        }

        final StringTokenizer tokenizer = new StringTokenizer(decodedUserAuthCredentials, ":");
        final String userName = tokenizer.nextToken();
        final String userPassword = tokenizer.nextToken();

        return "admin".equals(userName) && "admin".equals(userPassword);
      }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>test</display-name>
  <servlet>
    <servlet-name>
        AppContoller
    </servlet-name>
    <servlet-class>
        com.test.control.web.AppController
    </servlet-class>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>
        AppController
    </servlet-name>
    <url-pattern>
        /control/*
    </url-pattern>
  </servlet-mapping>
   
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
   <filter>
      <filter-name>AuthenticationFilter</filter-name>
      <filter-class>com.test.control.web.api.RestAuthenticationFilter</filter-class>
   </filter>
   <filter-mapping>
      <filter-name>AuthenticationFilter</filter-name>
      <url-pattern>/control/*</url-pattern>
   </filter-mapping>

</web-app>

我可以知道我的代码有什么问题吗?

如果我在邮递员的授权类型下选择不记名令牌、API 密钥,它会命中 RestAuthenticationFilter 方法,但当我选择基本身份验证时则不会。

java rest servlet-filters servlet-3.0
1个回答
0
投票

您已经创建了一个自定义过滤器,您仍然需要使用类似的东西将其添加到安全过滤器链中

@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http
        // ...
        .addFilterBefore(new RestAuthenticationFilter(), AuthorizationFilter.class); 
    return http.build();
}

提示:您可以从 OncePerRequestFilter 扩展,而不是实现 Filter,它是过滤器的基类,它提供带有 HttpServletRequest 和 HttpServletResponse 参数的 doFilterInternal 方法以避免强制转换。

您还可以参考 docs 来帮助您了解默认情况下如何处理基本身份验证,您可以使用它来提供一些实现,而不是创建自己的类

© www.soinside.com 2019 - 2024. All rights reserved.