0
点赞
收藏
分享

微信扫一扫

SpringSecurity实现”记住我“功能

唯米天空 2022-01-31 阅读 67

文章目录


功能: 简化用户每次登录都要输入用户名和密码的麻烦,提高用户体验

1、配置类

注意:
一定要添加lazy注解防止依赖循环

  @Resource
    @Lazy
    private UserServiceImpl userService;
    @Resource
    @Lazy
    private PersistentTokenRepository persistentTokenRepository;
package com.atmae.securitydemo.config;

import com.atmae.securitydemo.handle.MyAccessDeniedHandler;
import com.atmae.securitydemo.service.impl.UserServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
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.annotation.Resource;
import javax.sql.DataSource;

/**
 * @author Mae
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Resource
    private MyAccessDeniedHandler myAccessDeniedHandler;
    @Resource
    @Lazy
    private UserServiceImpl userService;
    @Resource
    private DataSource dataSource;
    @Resource
    @Lazy
    private PersistentTokenRepository persistentTokenRepository;

    @Bean
    public PersistentTokenRepository getPersistentTokenRepository() {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        /** 自动建表 第一次启动 第二次注释掉即可会报错*/
     /**   jdbcTokenRepository.setCreateTableOnStartup(true);*/
        jdbcTokenRepository.setDataSource(dataSource);
        return jdbcTokenRepository;
    }

    @Bean
    public PasswordEncoder getPw() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /** 表单提交*/
        http.formLogin()
                .usernameParameter("username")
                .passwordParameter("password")
                /** 当发现/login时 认为是登录 需和表单提交地址相同*/
                .loginProcessingUrl("/login")
                /** 自定义登录页面*/
                .loginPage("/login.html")
                /** 成功后执行post请求*/
                .successForwardUrl("/index")
                /** 失败后执行post请求*/
                .failureForwardUrl("/error");
        http.authorizeHttpRequests()
                /** 放行*/
                .antMatchers("/error.html").permitAll()
                .antMatchers("/login.html").permitAll()
                .antMatchers("/**/*.png").permitAll()
                /** 正则表达式*/
                .regexMatchers(".+[.]png").permitAll()
                /** 权限管理*/
                /**  .antMatchers("/member.html").hasAnyAuthority("admin")*/
                /** 角色判断*/
                /**  .antMatchers("/member.html").hasRole("student")*/
                /** 所有请求都必须被认证*/
                .anyRequest().authenticated();
        /** 关闭防火墙*/
        http.csrf().disable();
        /** 异常处理*/
        http.exceptionHandling()
                .accessDeniedHandler(myAccessDeniedHandler);
        /**记住我功能*/
        http.rememberMe()
                /** 自定义登录逻辑*/
                .userDetailsService(userService)
                /** 失效时间 60s*/
                .tokenValiditySeconds(60)
                /** 持久层登录*/
                .tokenRepository(persistentTokenRepository);
    }
}

2、自定义逻辑

package com.atmae.securitydemo.service.impl;

import com.atmae.securitydemo.mapper.UserMapper;
import com.atmae.securitydemo.pojo.User;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @author Mae
 */
@Service
public class UserServiceImpl implements UserDetailsService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        /** 查询数据库判断用户名是否存在*/
        User user = userMapper.findUserByUsername(username);
        System.out.println(user);
        if (user == null) {
            throw new UsernameNotFoundException("用户名没有找到");
        }
        /** 把查询出的密码(注册时已经过加密)进行解析,或者直接把密码放入构造方法*/
        String password = passwordEncoder.encode(user.getPassword());
        return new org.springframework.security.core.userdetails.User(username, password, AuthorityUtils
                .commaSeparatedStringToAuthorityList("admin,normal0,ROLE_student0"));
    }
}

3、登陆页

记住我的name一定要是 remember-me 否则需要自己配置

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页</title>
</head>
<body>
<form action="/login" method="post">
    <label for="username">用户名:<input type="text" id="username" name="username" placeholder="请输入用户名"></label><br/>
    <label for="password">密码:<input type="password" id="password" name="password" placeholder="请输入密码"></label><br/>
    <label for="remember-me">
        记住我:
        <input id="remember-me" type="checkbox" name="remember-me" value="1"/>
    </label><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

4、持久层和控制层

package com.atmae.securitydemo.controller;

import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author Mae
 */
@Controller
public class UserController {

    @Secured("ROLE_student0")
    @PreAuthorize("hasRole('ROLE_student0')") /** 可以不以Role开头*/
    @RequestMapping("/index")
    public String indexPage() {
        return "redirect:index.html";
    }

}
package com.atmae.securitydemo.mapper;

import com.atmae.securitydemo.pojo.User;
import org.apache.ibatis.annotations.Mapper;

/**
 * @author Mae
 */
@Mapper
public interface UserMapper {

    /**
     * 根据用户名查询用户
     * @param username 用户名
     * @return 用户
     */
    User findUserByUsername(String username);
}

5、功能

第一次登录
在这里插入图片描述
在这里插入图片描述
自动生成的数据表
在这里插入图片描述

第二次登录直接进入登录页
在这里插入图片描述
关闭浏览器直接进入主页则需重新登陆
在这里插入图片描述

举报

相关推荐

0 条评论