我需要公开其余的 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 方法,但当我选择基本身份验证时则不会。
您已经创建了一个自定义过滤器,您仍然需要使用类似的东西将其添加到安全过滤器链中
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
// ...
.addFilterBefore(new RestAuthenticationFilter(), AuthorizationFilter.class);
return http.build();
}
提示:您可以从 OncePerRequestFilter 扩展,而不是实现 Filter,它是过滤器的基类,它提供带有 HttpServletRequest 和 HttpServletResponse 参数的 doFilterInternal 方法以避免强制转换。
您还可以参考 docs 来帮助您了解默认情况下如何处理基本身份验证,您可以使用它来提供一些实现,而不是创建自己的类