让我们来看看基于表单的登录在 Spring Security 中是如何工作的。首先,我们看到如何将用户重定向到登录表单。
该图构建了我们的 SecurityFilterChain 图。
默认情况下,Spring Security 表单登录处于启用状态。但是,一旦提供了任何基于Servlet的配置,就必须显式提供基于表单的登录。可以在下面找到最低限度的显式Java配置:
protected void configure(HttpSecurity http) {
http
// ...
.formLogin(withDefaults());
}
在这个配置中,Spring Security 将呈现一个默认的登录页面。大多数生产应用程序都需要自定义登录表单。
下面的配置演示了如何提供自定义登录表单:
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.formLogin(form -> form
.loginPage("/login")
.permitAll()
);
}
当在 springsecurity 配置中指定登录页面时,您负责呈现该页面。下面是一个 Thymeleaf 模板,它生成一个 HTML 登录表单,该表单遵循/login 的登录页面:
DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<title>Please Log Intitle>
head>
<body>
<h1>Please Log Inh1>
<div th:if="${param.error}">
Invalid username and password.div>
<div th:if="${param.logout}">
You have been logged out.div>
<form th:action="@{/login}" method="post">
<div>
<input type="text" name="username" placeholder="Username"/>
div>
<div>
<input type="password" name="password" placeholder="Password"/>
div>
<input type="submit" value="Log in" />
form>
body>
html>
关于默认的 HTML 表单有几个关键点:
许多用户只需要自定义登录页面。但是,如果需要,上面的所有内容都可以通过额外的配置进行定制。
如果您正在使用 SpringMVC,那么您将需要一个控制器来将 GET /login 映射到我们创建的登录模板。一个最小的样例 LoginController 可以看到如下:
@Controller
class LoginController {
@GetMapping("/login")
String login() {
return "login";
}
}
让我们来看看在 Spring Security 中 HTTP 基本身份验证是如何工作的。首先,我们看到 WWW-Authenticate 标头被发送回未经身份验证的客户端。
该图构建了我们的 SecurityFilterChain 图。
当客户端收到 WWW-Authenticate 标头时,它知道应该使用用户名和密码重试。下面是处理用户名和密码的流程。
该图构建了我们的 SecurityFilterChain 图:
Spring Security 的 HTTP 基本身份验证支持在默认情况下是启用的。但是,一旦提供了任何基于 servlet 的配置,就必须显式地提供 HTTP Basic。
一个最小的,显式的配置可以在下面找到:
protected void configure(HttpSecurity http) {
http
// ...
.httpBasic(withDefaults());
}
警告: 您不应该在现代应用程序中使用摘要式身份验证,因为它被认为是不安全的。最明显的问题是必须以明文、加密或 md5格式存储密码。所有这些存储格式都是不安全的。相反,您应该使用单向自适应密码散列(即 bCrypt、 PBKDF2、 SCrypt 等)来存储凭据,而这是摘要身份验证不支持的。
摘要身份验证试图解决基本身份验证的许多弱点,特别是通过确保永远不会跨网络以明文形式发送凭据。许多浏览器支持摘要式身份验证。
管理 HTTP 摘要认证的标准是由 RFC 2617定义的,它更新了 RFC 2069规定的摘要认证标准的早期版本。大多数用户代理实现 RFC 2617。Spring Security 的 Digest Authentication 支持与 RFC 2617规定的“ auth”质量保护(qop)兼容,RFC 2617还为向下兼容提供了 RFC 2069。如果您需要使用未加密的 HTTP (即不使用 TLS/HTTPS)并希望最大限度地提高认证过程的安全性,那么摘要认证被认为是一个更有吸引力的选择。然而,每个人都应该使用 HTTPS。
摘要式认证的核心是“ nonce”。这是服务器生成的值。的 nonce 采用了以下格式:
base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
expirationTime: The date and time when the nonce expires, expressed in milliseconds
key: A private key to prevent modification of the nonce token
您需要确保使用 NoOpPasswordEncoder 配置不安全的纯文本密码存储。下面提供一个使用 Java 配置配置摘要式身份验证的例子:
@Autowired
UserDetailsService userDetailsService;
DigestAuthenticationEntryPoint entryPoint() {
DigestAuthenticationEntryPoint result = new DigestAuthenticationEntryPoint();
result.setRealmName("My App Relam");
result.setKey("3028472b-da34-4501-bfd8-a355c42bdf92");
}
DigestAuthenticationFilter digestAuthenticationFilter() {
DigestAuthenticationFilter result = new DigestAuthenticationFilter();
result.setUserDetailsService(userDetailsService);
result.setAuthenticationEntryPoint(entryPoint());
}
protected void configure(HttpSecurity http) throws Exception {
http
// ...
.exceptionHandling(e -> e.authenticationEntryPoint(authenticationEntryPoint()))
.addFilterBefore(digestFilter());
}