SpringSecurity-8-Automatic login and logout function implementation

SpringSecurity-8-Automatic login and logout function implementation

Implementation of automatic login

When we log in to a certain website, we will use the account and password to log in, but we don't want to close the browser every time , we don't want to re-enter the account and password every time, to fit the user's login experience and bring convenience to the user, We use the automatic login function to save the login information in the browser's cookie, so that the user will automatically verify and create a new login status when they visit next time. But this also brings the danger of information leakage to users .

Automatic login process

  1. After the user chooses to remember me successfully logged in, a cookie will be generated on the server and returned to the browser. The default name of the cookie is remember-me and the value is token.

  2. When the user revisits, the token value corresponding to the remember-me cookie will be checked first. If the token value exists, it will be checked whether the username, serial number and token value in the token value are the same as those generated by the server. If they are the same, they will pass. And the system will also regenerate a new token, the serialization series remains unchanged, delete the old cookie, regenerate a new cookie and save it on the client

  3. If the cookie does not exist, or the username, serialized series, and token are different from those on the server, it will return to the login page.

Because cookies may be stolen, if the application security is relatively high, then do not use the remember-me function.

Hash decryption scheme

It is very simple for SpringSecurity to implement the automatic login function

Modify login.html

We need to add remember me function in login.html, the html implementation is as follows

<!--suppress ALL-->
<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>springboot葵花宝典登录页面</title>
    <!-- Tell the browser to be responsive to screen width -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>springboot葵花宝典登录页面</h1>
<form  th:action="@{/login/form}" action="index.html" method="post">
    <span>用户名称</span><input type="text" name="username" /> <br>
    <span>用户密码</span><input type="password" name="password" /> <br>
    <div >
        <input name="code" type="text" class="form-control" placeholder="验证码">
        <img onclick="this.src='/code/image?'+Math.random()" src="/code/image" alt="验证码" />
    </div> <br>
    <span>记住我</span><input type="checkbox" name="remember-me" >  <br>
    <div th:if="${param.error}">
        <span th:text="${session.SPRING_SECURITY_LAST_EXCEPTION.message}" style="color:#ff0000">用户名或 密码错误</span>
    </div>
    <input type="submit" value="登陆">
</form>
</body>
</html>

复制代码

After modifying the results, the login page is displayed as follows:

图片

Modify LearnSrpingSecurity

Add remember my configuration in the configure(HttpSecurity http) method, the code is implemented as follows

图片

test

重新启动程序,使用浏览器访问http://localhost:8888/login/page,然后输入账号密码进行登录,结果如下

图片

从图上我们可以看出来,勾选“Remember me”可选框(简写为Remember-me),按照正常的流程登录,并在 开发者工具中查看浏览器cookie,可以看到除JSESSIONID外多了一个值。

cookie个性化配置

在实际的开发过程中,我们还可以根据需求做一些个性化的设置,如下:

.rememberMe()
    .rememberMeParameter("remember-me-new")
    .rememberMeCookieName("remember-me-cookie")

复制代码
  • 通过rememberMeParameter设置from表单“自动登录”勾选框的参数名称。如果这里改了,from表单中checkbox的name属性要对应的更改。如果不设置默认是remember-me。

  • rememberMeCookieName设置了保存在浏览器端的cookie的名称,如果不设置默认也是remember-me。如下图中查看浏览器的cookie。

图片

持久化令牌方案

持久化令牌方案是交互方式上和散列加密方案一致,都是用户勾选remember-me后,将生成的令牌发送到用户的客户端,用户在下次进行访问的时候会读取该令牌,不同的是会将数据保存到数据库中。

添加数据库依赖

我们在项目中的pom.xml中添加数据库依赖

   <!--mysql驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!--mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>

复制代码

application.yml中添加数据库配置

spring:
  thymeleaf:
    cache: false
  datasource:
    url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=utf-8&useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

复制代码

使用 JdbcTokenRepository 实现类

在LearnSrpingSecurity配置类中注入DataSourceJdbcTokenRepositoryImpl,实现如下

    @Autowired
    private DataSource dataSource;
    
    @Bean
    public JdbcTokenRepositoryImpl jdbcTokenRepository(){

        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }


复制代码

安全配置 LearnSrpingSecurity#confifigure(HttpSecurity http)

在LearnSrpingSecurity的confifigure(HttpSecurity http)方法中添加如下配置

                .and()
                .rememberMe()
                .userDetailsService(customUserDetailsService)
                .tokenRepository(jdbcTokenRepository())
                .tokenValiditySeconds(60)
                .rememberMeParameter("remember-me-test")
                .rememberMeCookieName("remember-me-cookie")

复制代码

测试效果

  • 重启项目后,数据库会自动创建表 persistent_logins

  • 访问首页跳转到登录页面,登录成功后,查看浏览器 cookies,保存 token 值,在数据库中也有数据。

  • 再重启,Session会清除。再次访问首页,不会跳转到登录页,因为上次已经记录了。这时浏览器Cookie中保存的token从数据库查找用户名,然后进行自动登录。

图片

报错

Caused by: java.sql.SQLSyntaxErrorException: Table 'persistent_logins' already exists

解决方法:

将JdbcTokenRepositoryImpl方法中jdbcTokenRepository.setCreateTableOnStartup(true)注释掉

    @Bean
    public JdbcTokenRepositoryImpl jdbcTokenRepository(){

        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        //jdbcTokenRepository.setCreateTableOnStartup(true);
        return jdbcTokenRepository;
    }

复制代码

退出系统

其实使用Spring Security进行logout非常简单,只需要在spring Security配置类配置项上加上这样一行代码:http.logout()。

图片

修改index.html

我们在index.html中添加退出系统功能,实现如下

<!--suppress ALL-->
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8" />
    <title>springboot葵花宝典管理系统</title>
</head>
<body>
    <a th:href="@{/logout}" href="login.html"  > <span>退出系统</span> </a>
    <h1>springboot葵花宝典管理系统</h1>
    <br>
    <a href="/syslog">日志管理</a>
    <br>
    <a href="/sysuser">用户管理</a>
</body>

复制代码

测试

重新启动项目后,登录成功后展示页面如下,退出登录后,我们发现remember-me-cookie已经删除。虽然我们简简单单的实现了logout功能,是不是还不足够放心?我们下面就来看一下Spring Security默认在logout过程中帮我们做了哪些动作。

  • 当前session失效,即:logout的核心需求,session失效就是访问权限的回收。

  • 删除当前用户的 remember-me“记住我”功能信息

  • clear清除当前的 SecurityContext

  • 重定向到登录页面,loginPage配置项指定的页面

图片

个性化配置

虽然Spring Security默认使用了/logout作为退出处理请求路径,登录页面作为退出之后的跳转页面。这符合绝大多数的应用的开发逻辑,但有的时候我们需要一些个性化设置,如下

                .and()
                .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login/page")
                .deleteCookies("JSESSIONID")

复制代码
  • 指定logoutUrl配置修改默认的logout路径,同时html退出按钮的请求url也要修改

  • 指定logoutSuccessUrl配置,指定退出之后的跳转页面

  • 使用deleteCookies删除指定的cookie,参数为cookie的名称

如果您觉得本文不错,欢迎关注,点赞,收藏支持,您的关注是我坚持的动力!

公众号springboot葵花宝典主要分享JAVA技术,主要包含SpringBoot、SpingCloud、Docker、中间件等技术

原创不易,转载请注明出处,感谢支持!如果本文对您有用,欢迎转发分享!

Guess you like

Origin juejin.im/post/7079656997812961311