实现原理
- 认证成功后通过cookie向浏览器中存入加密字符串,并且向数据库中存入加密字符串和用户信息字符串。
- 再次访问获取cookie信息,使用加密字符串到数据库中进行比对,如果查询到对应的信息,认证成功,可以登录。
spring security底层实现
具体实现
在
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.rixin.springsecuritydemo3.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
UserDetailsService userDetailsService;
//注入数据源
@Autowired
private DataSource dataSource;
//配置操作数据库对象
@Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource);
//jdbcTokenRepository.setCreateTableOnStartup(true); 启动时创建persistent_logins表
return jdbcTokenRepository;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//退出
http.logout().logoutUrl("/logout").logoutSuccessUrl("/test/hello").permitAll();
//配置没有权限访问跳转自定义页面
http.exceptionHandling().accessDeniedPage("/unauth.html");
//自定义用户登录页面
http.formLogin()
.loginPage("/login.html") //登录页面设置
.loginProcessingUrl("/user/login") //登录访问路径
.defaultSuccessUrl("/success.html").permitAll() //登录成功后的跳转路径
.and().authorizeRequests() //定义哪些url被保护,哪些不被保护
.antMatchers("/","/test/hello","/user/login").permitAll() //访问这些路径不需要认证
//.antMatchers("/test/index").hasAuthority("admins") //当前登录用户,只有具有admins权限才可以访问这个路径
//.antMatchers("/test/index").hasAnyAuthority("admins,manager")
//.antMatchers("/test/hello").hasRole("sale")
.antMatchers("/test/hello").hasAnyRole("sale")
.anyRequest().authenticated()
//
.and().rememberMe().tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(3600) //设置有效时长,单位秒
.userDetailsService(userDetailsService) //设置userDetailsService底层来操作数据库
.and().csrf().disable(); //关闭csrf防护
}
}
最后在登录页面添加记住我复选框:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/user/login" method="post">
username:<input type="text" name="username"/>
password:<input type="password" name="password"/>
<input type="submit" value="login"/>
<input type="checkbox" name="remember-me" title="记住我"/>自动登录
</form>
</body>
</html>
版权声明:本文为qq_41242680原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。