spring security 自动登录 --- 心得
1.前言
仍然是使用cookie存储登录数据,但是存储的数据 由 spring security自动创建 ,当登出后自动删除cookie,
如果不登出也仍在生命周期内,关闭浏览器再打开将会自动登录,无需手动再登录。
2.操作
需要在设置有spring security 的spring boot 工程基础上【详细可查看我的其他随笔,有详细记载,具体操作这里不解释】加上下面配置
(1)
security 配置里有两种写法 【但是只能选择一种】
方法一: 使用注解风格的Java配置
完整的security配置

package com.example.security5500.securityConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.stereotype.Component; //这个加不加无所谓 @Configuration //开启security自定义配置 @EnableWebSecurity //开启 Controller层的访问方法权限,与注解@PreAuthorize("hasRole('ROLE_admin')")配合,会拦截注解了@PreAuthrize注解的配置 // 想要@PreAuthorize正确执行 ,权限关键字必须带前缀 ROLE_ ,后面的部分可以随便写!!!!靠,琢磨了4小时了 ,终于找到原因了 @EnableGlobalMethodSecurity(prePostEnabled = true) //, securedEnabled = true public class WebSecurityConfig extends WebSecurityConfigurerAdapter { //实例自定义登录校验接口 【内部有 数据库查询】 @Autowired private DbUserDetailsService dbUserDetailsService; // @Bean // @Override // protected AuthenticationManager authenticationManager() throws Exception { // return super.authenticationManager(); // } //忽略拦截的静态文件路径 @Override public void configure(WebSecurity web) throws Exception { web.ignoring() .antMatchers( "/js/**", "/css/**", "/img/**", "/webjars/**"); } //拦截规则设置 @Override protected void configure(HttpSecurity http) throws Exception { http //允许基于使用HttpServletRequest限制访问 //即授权请求设置 .authorizeRequests() //设置不拦截页面,可直接通过,路径访问 "/", "/index", 则不拦截, .antMatchers("/", "/index", "/hhk/**") //是允许所有的意思 .permitAll() // //访问 /hai 需要admin权限 ,无权限则提示 403 // .antMatchers("/hai").hasAuthority("admin") // //访问 /kk 需要admin或user权限 ,无权限则提示 403 // .antMatchers("/kk").hasAnyAuthority("admin", "user") // //路径/admin/**所有的请求都需要admin权限 ,无权限则提示 403 // .antMatchers("/admin/**").hasAuthority("admin") //其他页面都要拦截,【需要在最后设置这个】 .anyRequest().authenticated() .and() //设置自定义登录页面 //即开启登录设置 .formLogin() //指定自定义登录页面的访问虚拟路径 .loginPage("/login") .permitAll() .and() // 添加退出登录支持。当使用WebSecurityConfigurerAdapter时,这将自动应用。默认情况是,访问URL”/ logout”,使HTTP Session无效 // 来清除用户,清除已配置的任何#rememberMe()身份验证,清除SecurityContextHolder,然后重定向到”/login?success” //即开启登出设置 .logout() // //指定的登出操作的虚拟路径,需要以post方式请求这个 http://localhost:5500/mylogout 才可以登出 ,也可以直接清除用户认证信息达到登出目的 // .logoutUrl("/mylogout") //使httpsession失效 .invalidateHttpSession(true) //清除认证信息 .clearAuthentication(true) //登出请求匹配器,新建一个蚂蚁路径请求匹配器 ,与 .logoutUrl("/mylogout")效果一样 .logoutRequestMatcher(new AntPathRequestMatcher("/mylogout")) //登出成功后访问的地址 .logoutSuccessUrl("/home") .permitAll() .and() //开启记住我设置,用于自动登录 .rememberMe() //密钥 .key("unique-and-secret") //存在cookie的用户名[用于cookie名] .rememberMeCookieName("remember-me-cookie-name") //生命周期,单位毫秒 .tokenValiditySeconds(24 * 60 * 60); //登陆后"选择记住我" ,会生成cookie ,登出则会自动删除该cookie , 只要不登出且未超出生命周期 ,那么关闭浏览器后再次访问将自动登录 // [name] [value] [domain] [path] [expires/max-age] [size] [httponly] [priority] //remember-me-cookie-name eGk6MTU5MTIwODAzNDk5MTozZWUyN2FlMmEwMWQxNDczMDhhY2ZkYTAxZWQ5ZWQ5YQ localhost / 2020-06-03T18:13:54.992Z 89 ✓ Medium } /** * 添加 UserDetailsService, 实现自定义登录校验,数据库查询 */ @Override protected void configure(AuthenticationManagerBuilder builder) throws Exception { //注入用户信息,每次登录都会来这查询一次信息,因此不建议每次都向mysql查询,应该使用redis //密码加密 builder.userDetailsService(dbUserDetailsService); // .passwordEncoder(passwordEncoder()); } /** * BCryptPasswordEncoder相关知识: * 用户表的密码通常使用MD5等不可逆算法加密后存储,为防止彩虹表破解更会先使用一个特定的字符串(如域名)加密,然后再使用一个随机的salt(盐值)加密。 * 特定字符串是程序代码中固定的,salt是每个密码单独随机,一般给用户表加一个字段单独存储,比较麻烦。 * BCrypt算法将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题。 */ @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } // /** // * 选择加密方式 ,密码不加密的时候选择 NoOpPasswordEncoder,不可缺少,否则报错 // * java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null" // */ // @Bean // public static PasswordEncoder passwordEncoder() { // return NoOpPasswordEncoder.getInstance(); // } }
方法二: xml风格
xml源码

<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <http> <!--设置不拦截的路径--> <!-- 登录路径--> <intercept-url pattern="/login" access="permitAll()"/> <!-- 静态文件路径--> <intercept-url pattern="/js/**" access="permitAll()"/> <intercept-url pattern="/css/**" access="permitAll()"/> <intercept-url pattern="/img/**" access="permitAll()"/> <intercept-url pattern="/webjars/**" access="permitAll()"/> <!-- 设置路径需要的指定权限 --> <intercept-url pattern="/hai" access="hasAuthority('admin')"/> <!-- 其他路径都需要拦截认证--> <intercept-url pattern="/**" access="isAuthenticated()"/> <!--Spring Security 4.0以后默认开启宽展请求伪造保护,这里配置禁用,不安全的操作。--> <csrf disabled="true"/> <!-- 表单登录指定路径--> <form-login login-page="/login"/> <!-- 登出操作--> <!-- 分别是清除session , 指定登出路径 ,指定登出成功后路径--> <logout invalidate-session="true" logout-url="/logout" logout-success-url="/login?logout"/> <!-- 记住我[自动登录]设置 --> <!-- 三个参数分别是 密钥 ,存在cookie的用户名[用于cookie名] ,存放的生命周期[单位毫秒] --> <remember-me key="unique-and-secret" remember-me-cookie="remember-me-cookie-name" token-validity-seconds="86400"/> </http> <!-- //在内存中进行注册公开内存的身份验证信息 // // 在内存中添加 用户名 ,密码 , 权限--> <authentication-manager> <authentication-provider> <user-service> <user name="user" password="password" authorities="ROLE_USER"/> </user-service> </authentication-provider> </authentication-manager> </beans:beans>
需要在启动类导入xml文件
package com.example.security5500; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.web.servlet.config.annotation.EnableWebMvc; @SpringBootApplication //设置mapper接口包位置 @MapperScan(basePackages = "com.example.security5500.dao") // // 当使用xml的方式配置时,开启此注解,将会注释掉WebSecurityConfig文件配置,该xml功能有同等效果 // @ImportResource("classpath:security/spring-security-config.xml") public class Security5500Application { public static void main(String[] args) { SpringApplication.run(Security5500Application.class, args); } }
使用xml 则不可以使用 注解 @EnableWebSecurity ,会导致失效
(2)在前端的自定义login.html 表单里添加“记住我”的单选框标签 ,name属性不可更改
完整源码

<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3"> <head> <title>Spring Security自定义</title> </head> <body> <div th:if="${param.error}"> Invalid username and password. </div> <div th:if="${param.logout}"> You have been logged out. </div> <!-- 表单的name属性不可变 --> <form th:action="@{/login}" method="post"> <div><label> User Name : <input type="text" name="username"/> </label></div> <div><label> Password: <input type="password" name="password"/> </label></div> <div class="form-group"> <label> <input id="remember-me" name="remember-me" type="checkbox"/> 记住我 </label> </div> <div><input type="submit" value="Sign In"/></div> </form> <hr> <br> lalallalalal但是开发建设士大夫立刻 </body> </html>
3.测试
(1)启动 ,进入登录页面
(2)勾选记住我登录 ,此时cookie只有一个jsession数据
登陆后查看cookie ,多了个cookie数据
(2)关闭浏览器再打开该网址 ,会发现可直接进入,不需要手动输入账户密码登录
(3)登出后,查看cookie ,会发现cookie数据没有了,只剩下jsession
本文来自博客园,作者:岑惜,转载请注明原文链接:https://www.cnblogs.com/c2g5201314/p/13036082.html
响应开源精神相互学习,内容良币驱除劣币
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现