Spring Security(五)其他常用功能

本文介绍了 Spring Security 的一些常用功能,包含 Remember Me 功能的设置,如何在 Thymeleaf 中使用 Spring Security 登录信息,如何退出登录,csrf 功能的简单介绍。

Remember Me 功能

默认情况下,用户的登录信息存储在 Session 域,关闭浏览器,就需要重新登录。

Spring Security 支持"Remember Me"(记住我)功能,用户在登陆时添加 remember-me 复选框,取值为 true,Spring Security 就可以自动将用户信息储存到数据源中,一段时间内可以不登陆进行访问。

  1. 配置 RememberMeConfig(主要是为了使用 dataSource 创建 Repository)

    @Configuration
    public class RememberMeConfig {
    
        @Autowired
        private DataSource dataSource;
    
        @Bean
        PersistentTokenRepository persistentTokenRepository() {
            JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
            // 创建表,我们可以在第一次启动时加入这行
            // jdbcTokenRepository.setCreateTableOnStartup(true);
            jdbcTokenRepository.setDataSource(dataSource);
            return jdbcTokenRepository;
        }
    }
    
  2. 配置 WebSecurityConfig,将需要记住的 UserDetailsService 和存储目标的 TokenRepository 进行配置。

            http.rememberMe()
    	            // 设置 token 的有效时间为 7 天,默认是 120s
                    .tokenValiditySeconds(60 * 60 * 24 * 7)
                    .userDetailsService(userDetailsService)
                    .tokenRepository(persistentTokenRepository);
    
  3. 前端页面需要响应地进行修改,增加 remember-me 属性:

    <form action="/login" method="post">
        用户名:<input type="text" name="myUsername"/> <br>
        密码:<input type="password" name="myPassword"/> <br>
        记住我:<input type="checkbox" name="remember-me" value="true"> <br>
        <input type="submit">
    </form>
    
  4. 登录一次后,会创建 persistent_logins 表,存储登陆用户的信息。

    image-20230712141239877

    此时,关闭浏览器重新启动,仍然可以直接访问(自己权限足够的)页面。

在 Thymeleaf 中使用登录信息

  1. 导入依赖

    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        <version>3.1.1.RELEASE</version>
    </dependency>
    
  2. 在 html 中可以通过 sec: authentication="XXX" 的形式获取各种信息:

    image-20230712143848715

    也可以使用各种函数进行 if 的权限判断,返回为真,标签生效:

    image-20230712144137904

退出登录

默认,Spring Security 的退出登录绑定在 /logout,访问 http://localhost:8080/logout 即可实现退出登录。

默认情况下,访问 /logout 会退出登录,然后跳转到 /login?logout 页面。如果想修改这个页面,可以在 WebSecurityConfig 配置:

        // 退出登录相关配置
        http.logout()
                .logoutSuccessUrl("/showLogin");

此外,http.logout() 还可以配置退出登录的地址、使用重定向、配置 Handler 等等。

关于 csrf

csrf 的全称是 Cross-Site Request Forgery「跨站请求伪造」,也被称为 One Click Attack 或 Session Riding,通过伪造用户请求访问受信任站点的非法请求访问。

客户端与服务器进行交互时,由于 HTTP 的无状态特性,引入了 Cookie 来记录客户端身份,在 Cookie 中会存放 Session id 用来识别客户端的身份,在跨域情况下,Session id 可能被第三方恶意劫持,通过这个 session id 向服务器发送请求,服务端就会认为其合法,从而造成风险。

我们前面为了方便,关闭了 csrf 功能:

http.csrf().disable();

将它注释掉,就开启 csrf 功能,此时,在登录页面,需要加上 _csrf 的相关配置:

<form action="/login" method="post">
    <input type="hidden" th:value="${_csrf.token}" name="_csrf" th:if="${_csrf}">
    用户名:<input type="text" name="myUsername"/> <br>
    密码:<input type="password" name="myPassword"/> <br>
    记住我:<input type="checkbox" name="remember-me"> <br>
    <input type="submit">
</form>

这样,在外域就无法直接访问 /login 页面进行登录了(必须通过 showLogin 页面访问 /login)。

小结

  • Remember Me 功能是通过在 WebSecurityConfig 类中进行配置 http.rememberMe() 实现的,需要配置 userDetailsService 和 tokenRepository。
  • 在 Thymeleaf 中使用登录信息需要导入 thymeleaf-extras-springsecurity5 依赖,然后就可以使用 sec:authorize 属性查看信息内容或使用权限表达式。
  • Spring Security 的退出登录默认绑定在 /logout,可以通过 http.logout() 进行配置。
  • csrf 是跨站请求伪造,开启 csrf 时,需要在前端发送页面加入参数 _csrf