如何使用 Spring Security 和 Vue.js 设置登录?

jmb*_*bds 3 java spring spring-security spring-boot vue.js

我目前正在使用 Spring(带有 Spring Security)和 Vue.js 开发一个 Web 应用程序。我之前构建过一些 Web 应用程序,但它们仅用于学校目的,因此在身份验证和授权方面它们大多不完整。所以,正如你所看到的,我在 Spring Boot 和 Spring Security 方面真的没有经验。

我的项目是按以下方式设置的:

项目文件夹

  • 项目服务器(Spring -> localhost:9000)
  • 项目网络(Vue.js CLI -> localhost:8080)

我正在遵循一个教程来实现 Spring Security,现在,我可以使用内置的登录表单,使用我存储在 MySQL 数据库中的凭据来验证我的用户。

问题是我不想使用这个登录页面,我想在我的前端项目中创建自己的登录页面。我已经查过了,我可以更改登录页面,但我相信它需要位于后端项目文件夹内的资源文件夹中。然而,我的项目不是这样设置的,我不想改变它(如果可能的话)。我以为我可以通过 URL 引用我的 API,但我注意到 Spring Security 在登录成功时不会发送 HTTP 200 响应,而是发送 HTTP 302 重定向响应。我见过禁用表单登录然后使用 JWT 进行身份验证的解决方案,但我也发现这不是一个好的做法,因为无法撤销此令牌。

这是我的 ApplicationSecurityConfig 的外观

@Configuration
@EnableWebSecurity
public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {

private final PasswordEncoder passwordEncoder;
private final ApplicationUserService applicationUserService;

@Autowired
public ApplicationSecurityConfig(PasswordEncoder passwordEncoder,
                                 ApplicationUserService applicationUserService) {
    this.passwordEncoder = passwordEncoder;
    this.applicationUserService = applicationUserService;
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .csrf().disable()
            .authorizeRequests()
            .antMatchers("/", "/css/*", "/js/*").permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .formLogin()
            .usernameParameter("email")
            .and()
            .logout()
                .logoutUrl("/logout")
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET"))
                .clearAuthentication(true)
                .invalidateHttpSession(true)
                .deleteCookies("JSESSIONID", "remember-me")
                .logoutSuccessUrl("/login");
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth
            .userDetailsService(applicationUserService)
            .passwordEncoder(passwordEncoder);
}
Run Code Online (Sandbox Code Playgroud)

}

那么,有没有办法创建外部登录页面并使用 Spring Security 身份验证和授权功能呢?

小智 6

这个问题有很多解决方案,主要取决于您的需求以及如何构建应用程序,以下是我想到的几个场景:

REST API + Vuejs + JWT

如果整个前端都是用 Vuejs 构建的,那么后端可能只包含发送和接收 JSON 的 REST API,在这种情况下,无状态身份验证机制效果更好,例如 JSON Web Token(JWT)。

在这种情况下,服务器公开一个端点,比方说/auth/login,您可以在其中发送用户名和密码,服务器将使用令牌进行应答。一旦 Vue 前端拥有有效的令牌,它必须将其作为请求标头的一部分发送给每个经过身份验证的后续 API 调用,这将确保用户是自称的用户并拥有访问 API 的正确权限。

JWT 的工作方式是由三部分组成:

  • 包含有关用于签署令牌的算法的信息的标头。
  • 包含有关登录用户的信息(用户名、角色、令牌到期日期、自定义字段等)的正文。
  • 签名由标头、主体的哈希值和只有服务器知道的密钥组成。

有了这些信息,服务器就可以验证用户是否拥有有效的令牌(该令牌是服务器在成功登录后生成的,并且未过期),而无需会话。

有关 JWT 的更多信息,请查看https://jwt.io/RFC 7519,如果您需要一个良好的 Java 实现,我过去使用过Auth0中的实现,效果非常好。

混合服务器端模板 + Vuejs + Cookie

在某些情况下,当前端的一部分由服务器中的某些模板引擎生成,而另一些则由客户端的 Vuejs 管理时,您将拥有一个混合应用程序,并且您可能已经有了基于会话的身份验证。如果是这种情况,您仍然可以集成身份验证,请记住,最后服务器仅向客户端发送一个 cookie,其中包含存储在服务器上的会话 ID,因此,如果您在每个请求中发回 cookie,服务器将识别该用户通过身份验证并允许调用 API。

这种情况下的问题是,您正在从不同的域发出请求,因此 cookie 不会被传播,您可以从 Vue 端配置 webpack 以在 project-server/src/main/resources/static 下构建项目并提供页面来自Spring,以便前端和后端位于同一域下,并且cookie应该与ajax请求一起发送。