Spring Security中的自动登录

Posted 爱上口袋的天空

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Security中的自动登录相关的知识,希望对你有一定的参考价值。

实现原理

  1. 认证成功后通过cookie向浏览器中存入加密字符串,并且向数据库中存入加密字符串和用户信息字符串。
  2. 再次访问获取cookie信息,使用加密字符串到数据库中进行比对,如果查询到对应的信息,认证成功,可以登录。

spring security底层实现

在这里插入图片描述

具体实现

创建数据表

CREATE TABLE `persistent_logins` (
 `username` VARCHAR(64) NOT NULL,
 `series` VARCHAR(64) NOT NULL,
 `token` VARCHAR(64) NOT NULL,
 `last_used` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE 
CURRENT_TIMESTAMP,
 PRIMARY KEY (`series`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

然后,在配置类中注入数据源,配置操作数据库对象,并且配置自动登录。
SecurityConfig.java

package com.kgf.security.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.sql.DataSource;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;


    //注入数据源
    @Autowired
    private DataSource dataSource;

    //配置操作数据库对象
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        //jdbcTokenRepository.setCreateTableOnStartup(true); 启动时创建persistent_logins表
        return jdbcTokenRepository;
    }

    /***
     * 设置登录的用户
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //这是使用内存的方式
//        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
//        String password = encoder.encode("123456");
//        auth.inMemoryAuthentication().withUser("test").password(password).roles("admin");
        //下面使用自定义接口实现类从数据库查询
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.formLogin()
                .loginPage("/login.html")//登录页面设置
                .loginProcessingUrl("/user/login")//登录访问路径,这个不需要自己写controller,配置即可,这个是spring security自动完成
                .defaultSuccessUrl("/success.html").permitAll()//登录成功之后跳转的路径
                .and().authorizeRequests()
                .antMatchers("/","/test/hello","/user/login").permitAll()//设置这些路径可以直接访问,不需要认证
                //1、hasAuthority方法
                //.antMatchers("/test/index").hasAuthority("admin")//需要用户具有admin角色权限才行
                //2、hasAnyAuthority方法
                .antMatchers("/test/index").hasAnyAuthority("admin,manager")//需要用户具有admin角色权限才行
                .anyRequest().authenticated()
                //
                .and().rememberMe().tokenRepository(persistentTokenRepository())
                .tokenValiditySeconds(3600) //设置有效时长,单位秒
                .userDetailsService(userDetailsService) //设置userDetailsService底层来操作数据库
                .and().exceptionHandling().accessDeniedPage("/unauth.html")//配置没有权限访问跳转自定义页面,必须配置在这里,配置在上面不起作用
                .and().logout().logoutUrl("/logout").logoutSuccessUrl("/test/hello").permitAll()//退出
                .and().csrf().disable();//关闭csrf防护
    }

    /***
     * 注入PasswordEncoder到spring中
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

}

最后在登录页面添加记住我复选框:

<!DOCTYPE html>
<!-- 需要添加
<html  xmlns:th="http://www.thymeleaf.org">
这样在后面的th标签就不会报错
 -->
<html  xmlns:th="http://www.thymeleaf.org">
<head lang="en">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <title>xx</title>
</head>
<body>


<h1>表单提交</h1>
<!-- 表单提交用户信息,注意字段的设置,直接是*{} -->
<form action="/user/login"  method="post">
    <input type="text" name="username" />
    <input type="text" name="password" />
    <input type="checkbox" name="remember-me" title="记住我"/>自动登录
    <input type="submit" />
</form>
</body>
</html>

注意:自动登录的name必须为remember-me

测试:

点击登录后查询返回的cookie

 

我们在访问接口:

 

 

以上是关于Spring Security中的自动登录的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security中的自动登录

Spring Security:无法让真正的用户使用显示过期的 SessionRegistry 登录

SpringBoot集成Spring Security——自动登录

如何从 Spring Security 中的 java 代码登录用户?

Spring Security七RememberMe配置

Spring Security 之 rememberMe 自动登录