springsecurity

本文介绍了如何在Spring Boot应用中使用Spring Security进行安全配置,包括引入依赖、设置用户名和密码的方式(配置文件、配置类、自定义实现类与数据库查询)、自定义登录页面、权限访问控制、用户注销、实现自动登录以及防止CSRF攻击。详细展示了各个配置步骤和关键代码,提供了一个完整的Spring Security实践示例。
摘要由CSDN通过智能技术生成

引入依赖

        

       <!--  引入springsecurity-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

设置用户名和密码

方式一配置文件application.properties

spring.security.user.name=xuliangjie
spring.security.user.password=123456

方式二配置类(配置类和配置文件同时设置,配置类生效)

package com.xu.securitydemo1.config;

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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

//第二种方式设置用户名和密码配置类
@Configuration
public class SecurityConfig  extends WebSecurityConfigurerAdapter {

    //继承这个类,需要重写父类的方法
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        //对密码进行加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String password = passwordEncoder.encode("123");

        //用auth设置用户名和密码
        //inMemoryAuthentication()放入内存,设置用户名,设置密码,设置权限
        auth.inMemoryAuthentication().withUser("lucy").password(password).roles("admin");
    }

    //PasswordEncoder是一个接口,BCryptPasswordEncoder是接口的一个实现类,返回PasswordEncoder类型的一个new实现类
    @Bean
    PasswordEncoder password() {
        return new BCryptPasswordEncoder();
    }
}

方式三自定义实现类(最实用,查数据库)

配置类和配置文件都写,配置类生效

这里演示的代码没有进行用户名检验,只要密码正确都能登录

以下是配置类

package com.xu.securitydemo1.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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;


//第三种方式设置用户名密码,自定义实现类
@Configuration
public class SecurityConfigByself extends WebSecurityConfigurerAdapter {


    //注入userdetailsservice 实现类
    @Autowired
    private UserDetailsService userDetailsService;

    //继承这个类,需要重写父类的方法
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        //设置UserDetailsService并且对密码加密,然后写一个实现类继承UserDetailsService,实现类查询数据库返回一个user对象包含用户名,密码,以及权限集合
        auth.userDetailsService(userDetailsService).passwordEncoder(password());
    }

    //PasswordEncoder是一个接口,BCryptPasswordEncoder是接口的一个实现类,返回PasswordEncoder类型的一个new实现类
    @Bean
    PasswordEncoder password() {
        return new BCryptPasswordEncoder();
    }
}

以下是实现类

package com.xu.securitydemo1.service;


import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

//第三种方式设置用户名密码,创建实现类
@Service("userDetailsService")//取别名,和自定义配置类注入的名字对应(也可以不写@Autowired会默认先根据类型匹配,再根据名字)
public class MyUserDetailsService implements UserDetailsService {


    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {

        //用户名,密码,权限集合(实际查数据库得到)
        String name = "marry";
        String password = new BCryptPasswordEncoder().encode("123");
        List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
        return new User(name,password,auths);
    }
}

******************************************************************************************************

方式三查询数据库实现

1.

#数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/securitydemo?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root

2.实体类

package com.xu.securitydemo1.entity;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
public class User {


    //private int id 不包含null,Integer可以包含为null的值
    private Integer id;
    private String username;
    private String password;
}

3.mapper

package com.xu.securitydemo1.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xu.securitydemo1.entity.User;
import org.springframework.stereotype.Repository;


@Repository
public interface UserMapper extends BaseMapper<User> {

}

4.service

package com.xu.securitydemo1.service;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xu.securitydemo1.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

//第三种方式设置用户名密码,创建实现类
@Service("userDetailsService")//取别名,和自定义配置类注入的名字对应(也可以不写@Autowired会默认先根据类型匹配,再根据名字)
public class MyUserDetailsService implements UserDetailsService {


    //用autowired需要在UserMapper加上repository,不加repository需要用resource
    //resource根据名称注入,Autowired根据类型注入
    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {

        //String s前端传过来一个用户名,根据用户名去查数据库
        //我理解的是User是一个关键字之类的,所以自动变成全路径
        QueryWrapper<com.xu.securitydemo1.entity.User> wrapper = new QueryWrapper<>();
        wrapper.eq("username", s);
        com.xu.securitydemo1.entity.User user = userMapper.selectOne(wrapper);

        //判断
        if (user == null) {
            throw new UsernameNotFoundException("用户名不存在");
        }

        //用户名,密码,权限集合(实际查数据库得到)
        String username = user.getUsername();
        String password = new BCryptPasswordEncoder().encode(user.getPassword());
        //权限集合我在数据库还没写,用这个测试
        List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
        return new User(username,password,auths);
    }
}

5.启动类

package com.xu.securitydemo1;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
//扫描mapper包去找到实现类
@MapperScan(basePackages = {"com.xu.securitydemo1.mapper"})//没有写mapper的实现类,basemapper里封装了实现类,basemapper的sql语句在一个枚举类里SqlMethod
public class  Securitydemo1Application {

    public static void main(String[] args) {
        SpringApplication.run(Securitydemo1Application.class, args);
    }

}

*********************************************************************************************

自定义登录页面

写在第三种方式的配置类里

package com.xu.securitydemo1.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;


//第三种方式设置用户名密码,自定义实现类
@Configuration
public class SecurityConfigByself extends WebSecurityConfigurerAdapter {


    //注入userdetailsservice 实现类
    @Autowired
    private UserDetailsService userDetailsService;

    //继承这个类,需要重写父类的方法
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        //设置UserDetailsService并且对密码加密,然后写一个实现类继承UserDetailsService,实现类查询数据库返回一个user对象包含用户名,密码,以及权限集合
        auth.userDetailsService(userDetailsService).passwordEncoder(password());
    }

    //PasswordEncoder是一个接口,BCryptPasswordEncoder是接口的一个实现类,返回PasswordEncoder类型的一个new实现类
    @Bean
    PasswordEncoder password() {
        return new BCryptPasswordEncoder();
    }


    //自定义登录页面
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.formLogin()                      //自定义登录页面
                .loginPage("/login.html")     //自定义页面地址
                .loginProcessingUrl("/user/login")       //登录提交表单之后访问的路径进行UserDetailsService的验证
                .defaultSuccessUrl("/test/index").permitAll()                //登录成功跳转到的路径
                .and().authorizeRequests()
                .antMatchers("/", "/test/hello", "/user/login").permitAll()    //设置哪些路径不需要登录认证可以直接访问
                .anyRequest().authenticated()   //表示所有请求都需要认证
                .and().csrf().disable();//关闭csrf防护
    }

}

********************************************************************************************************

权限访问

增删改查权限:

hasAuthority()方法只能写一个权限

 //表示当前登录的用户只有admins权限的才能访问/test/index
.antMatchers("/test/index").hasAuthority("admins")

hasAnyAuthority()方法有任一权限都可以访问

//hasAnyAuthority()方法有任一权限都可以访问
.antMatchers("/test/index").hasAnyAuthority("admins,manager")

用户的角色权限:

hasRole()方法和hasAuthority()类似,区别在于hasRole源码中会将sale变成ROLE_sale,所以数据库存储要写ROLE_sale

//hasRole()方法和hasAuthority()类似,区别在于hasRole源码中会将sale变成ROLE_sale,所以数据库存储要写ROLE_sale
.antMatchers("/test/index").hasRole("sale")

hasAnyRole()方法和hasAnyAuthority()类似,任一权限满足就可访问,也要加上ROLE_

//4.hasAnyRole()方法和hasAnyAuthority()类似,任一权限满足就可访问,也要加上ROLE_
.antMatchers("/test/index").hasAnyRole("sale,role")

***********************************************************************************************

配置由于没有权限跳转的页面

package com.xu.securitydemo1.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;


//第三种方式设置用户名密码,自定义实现类
@Configuration
public class SecurityConfigByself extends WebSecurityConfigurerAdapter {


    //注入userdetailsservice 实现类
    @Autowired
    private UserDetailsService userDetailsService;

    //继承这个类,需要重写父类的方法
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        //设置UserDetailsService并且对密码加密,然后写一个实现类继承UserDetailsService,实现类查询数据库返回一个user对象包含用户名,密码,以及权限集合
        auth.userDetailsService(userDetailsService).passwordEncoder(password());
    }

    //PasswordEncoder是一个接口,BCryptPasswordEncoder是接口的一个实现类,返回PasswordEncoder类型的一个new实现类
    @Bean
    PasswordEncoder password() {
        return new BCryptPasswordEncoder();
    }


    //自定义登录页面
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.formLogin()                      //自定义登录页面
                .loginPage("/login.html")     //自定义页面地址
                .loginProcessingUrl("/user/login")       //登录提交表单之后访问的路径进行UserDetailsService的验证
                .defaultSuccessUrl("/test/index").permitAll()                //登录成功跳转到的路径
                .and().authorizeRequests()
                .antMatchers("/", "/test/hello", "/user/login").permitAll()    //设置哪些路径不需要登录认证可以直接访问
                 //表示当前登录的用户只有admins权限的才能访问/test/index
                //1.hasAuthority()方法只能写一个权限
                //.antMatchers("/test/index").hasAuthority("admins")
                //2.hasAnyAuthority()方法有任一权限都可以访问
                //.antMatchers("/test/index").hasAnyAuthority("admins,manager")
                //3.hasRole()方法和hasAuthority()类似,区别在于hasRole源码中会将sale变成ROLE_sale,所以数据库存储要写ROLE_sale
                //.antMatchers("/test/index").hasRole("sale")
                //4.hasAnyRole()方法和hasAnyAuthority()类似,任一权限满足就可访问,也要加上ROLE_
                .antMatchers("/test/index").hasAnyRole("xxx")
                .anyRequest().authenticated()
                .and().csrf().disable();//关闭csrf防护


        //配置没有权限跳转的页面
        http.exceptionHandling().accessDeniedPage("/unauth.html");
    }

}

**************************************************************************************************************

授权注解

@Secured({"ROLE_sale"})

在启动类上加上@EnableGlobalMethodSecurity(securedEnabled = true)//开启注解配置权限

//这个注解的含义是当前用户具有ROLE_sale这个角色才访问下面的方法
@Secured({"ROLE_sale"})
@GetMapping("update")
public  String update() {
    return "update";
}

@PreAuthorize("hasAnyAuthority('admins')")

在启动类上加上@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)//开启注解配置权限
//这个注解表示当前用户有这个权限才能访问下面的方法
@PreAuthorize("hasAnyAuthority('admins')")
@GetMapping("upup")
public  String upup() {
    return "upup";
}

以上两个注解其实作用差不多,和配置类里的那几个类似,是否需要ROLE_前缀的区别

@PostAuthorize("hasAnyAuthority('admins')")

在启动类上加上@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)//开启注解配置权限

//这个注解是先执行方法再验证权限(感觉用处不大)
@PostAuthorize("hasAnyAuthority('admins')")
@GetMapping("xxxx")
public  String xxxx() {
    System.out.println("xxxxxxxxxxxxxxx");
    return "xxxx";
}

@PostFilter对返回的数据进行过滤

@PreFilter对前端传入的数据进行过滤

具体使用时再百度

***********************************************************************************************************

注销用户退出

package com.xu.securitydemo1.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;


//第三种方式设置用户名密码,自定义实现类
@Configuration
public class SecurityConfigByself extends WebSecurityConfigurerAdapter {


    //注入userdetailsservice 实现类
    @Autowired
    private UserDetailsService userDetailsService;

    //继承这个类,需要重写父类的方法
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        //设置UserDetailsService并且对密码加密,然后写一个实现类继承UserDetailsService,实现类查询数据库返回一个user对象包含用户名,密码,以及权限集合
        auth.userDetailsService(userDetailsService).passwordEncoder(password());
    }

    //PasswordEncoder是一个接口,BCryptPasswordEncoder是接口的一个实现类,返回PasswordEncoder类型的一个new实现类
    @Bean
    PasswordEncoder password() {
        return new BCryptPasswordEncoder();
    }


    //自定义登录页面
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.formLogin()                      //自定义登录页面
                .loginPage("/login.html")     //自定义页面地址
                .loginProcessingUrl("/user/login")       //登录提交表单之后访问的路径进行UserDetailsService的验证
                .defaultSuccessUrl("/success.html").permitAll()                //登录成功跳转到的路径
                .and().authorizeRequests()
                .antMatchers("/", "/test/hello", "/user/login").permitAll()    //设置哪些路径不需要登录认证可以直接访问
                 //表示当前登录的用户只有admins权限的才能访问/test/index
                //1.hasAuthority()方法只能写一个权限
                //.antMatchers("/test/index").hasAuthority("admins")
                //2.hasAnyAuthority()方法有任一权限都可以访问
                //.antMatchers("/test/index").hasAnyAuthority("admins,manager")
                //3.hasRole()方法和hasAuthority()类似,区别在于hasRole源码中会将sale变成ROLE_sale,所以数据库存储要写ROLE_sale
                //.antMatchers("/test/index").hasRole("sale")
                //4.hasAnyRole()方法和hasAnyAuthority()类似,任一权限满足就可访问,也要加上ROLE_
                .antMatchers("/test/index").hasAnyRole("sale")
                .anyRequest().authenticated()
                .and().csrf().disable();//关闭csrf防护


        //配置没有权限跳转的页面
        http.exceptionHandling().accessDeniedPage("/unauth.html");


        //退出跳转到其他页面     .logoutUrl("/logout")是点击退出的超链接地址     .logoutSuccessUrl("/test/hello")是退出成功后跳转的页面
        http.logout().logoutUrl("/logout").logoutSuccessUrl("/test/hello").permitAll();
    }

}

<body>
登录成功
<a href="/logout">退出</a>
</body>

**************************************************************************************************************

实现自动登录

流程:

 

通过这个实现类来操作数据库

配置类

package com.xu.securitydemo1.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 SecurityConfigByself extends WebSecurityConfigurerAdapter {


    //注入userdetailsservice 实现类
    @Autowired
    private UserDetailsService userDetailsService;

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

    //PersistentTokenRepository这个是相当于mapper,里面定义了操作数据库的方法
    //JdbcTokenRepositoryImpl是继承PersistentTokenRepository这个接口的实现类
    //JdbcTokenRepositoryImpl里有对数据库操作的具体内容
    //@Bean将这个对象交给spring管理
    @Bean
    public PersistentTokenRepository persistentTokenRepository() {

        //new操作数据库的对象
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();

        //设置数据源来操作具体的数据库
        jdbcTokenRepository.setDataSource(dataSource);

        //这句话的意思是自动创建表(已手动创建就不需要加)
        //jdbcTokenRepository.setCreateTableOnStartup(true);

        //返回操作数据库的对象
        return jdbcTokenRepository;
    }

    //继承这个类,需要重写父类的方法
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        //设置UserDetailsService并且对密码加密,然后写一个实现类继承UserDetailsService,实现类查询数据库返回一个user对象包含用户名,密码,以及权限集合
        auth.userDetailsService(userDetailsService).passwordEncoder(password());
    }

    //PasswordEncoder是一个接口,BCryptPasswordEncoder是接口的一个实现类,返回PasswordEncoder类型的一个new实现类
    @Bean
    PasswordEncoder password() {
        return new BCryptPasswordEncoder();
    }


    //自定义登录页面
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.formLogin()                      //自定义登录页面
                .loginPage("/login.html")     //自定义页面地址
                .loginProcessingUrl("/user/login")       //登录提交表单之后访问的路径进行UserDetailsService的验证
                .defaultSuccessUrl("/success.html").permitAll()                //登录成功跳转到的路径
                .and().authorizeRequests()
                .antMatchers("/", "/test/hello", "/user/login").permitAll()    //设置哪些路径不需要登录认证可以直接访问
                 //表示当前登录的用户只有admins权限的才能访问/test/index
                //1.hasAuthority()方法只能写一个权限
                //.antMatchers("/test/index").hasAuthority("admins")
                //2.hasAnyAuthority()方法有任一权限都可以访问
                //.antMatchers("/test/index").hasAnyAuthority("admins,manager")
                //3.hasRole()方法和hasAuthority()类似,区别在于hasRole源码中会将sale变成ROLE_sale,所以数据库存储要写ROLE_sale
                //.antMatchers("/test/index").hasRole("sale")
                //4.hasAnyRole()方法和hasAnyAuthority()类似,任一权限满足就可访问,也要加上ROLE_
                .antMatchers("/test/index").hasAnyRole("sale")
                .anyRequest().authenticated()
                //设置操作数据库的对象persistentTokenRepository(),就是在前面定义的
                .and().rememberMe().tokenRepository(persistentTokenRepository())
                //设置有效时长,秒为单位
                .tokenValiditySeconds(60)
                //用userDetailsService的底层去操作数据库
                .userDetailsService(userDetailsService)
                .and().csrf().disable();//关闭csrf防护


        //配置没有权限跳转的页面
        http.exceptionHandling().accessDeniedPage("/unauth.html");


        //退出跳转到其他页面     .logoutUrl("/logout")是点击退出的超链接地址     .logoutSuccessUrl("/test/hello")是退出成功后跳转的页面
        http.logout().logoutUrl("/logout").logoutSuccessUrl("/test/hello").permitAll();
    }

}

 

第一步创建数据库表:

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; 

第二步配置类里注入数据源,配置操作数据库的对象

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

//PersistentTokenRepository这个是相当于mapper,里面定义了操作数据库的方法
//JdbcTokenRepositoryImpl是继承PersistentTokenRepository这个接口的实现类
//JdbcTokenRepositoryImpl里有对数据库操作的具体内容
//@Bean将这个对象交给spring管理
@Bean
public PersistentTokenRepository persistentTokenRepository() {

    //new操作数据库的对象
    JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();

    //设置数据源来操作具体的数据库
    jdbcTokenRepository.setDataSource(dataSource);

    //这句话的意思是自动创建表(已手动创建就不需要加)
    //jdbcTokenRepository.setCreateTableOnStartup(true);

    //返回操作数据库的对象
    return jdbcTokenRepository;
}

第三步配置类配置自动登录

//设置操作数据库的对象persistentTokenRepository(),就是在前面定义的
.and().rememberMe().tokenRepository(persistentTokenRepository())
//设置有效时长,秒为单位
.tokenValiditySeconds(60)
//用userDetailsService的底层去操作数据库
.userDetailsService(userDetailsService)

第四步前端设置一个复选框来自动登录

<form action="/user/login" method="post">
    用户名:<input type="text" name="username"/>
    <br/>
    密码:<input type="password" name="password"/>
    <br/>
<!--   必须要叫remember-me,因为框架设置好的只会找这个名字-->
    <input type="checkbox" name="remember-me">自动登录
    <br/>
    <input type="submit" value="login"/>
</form>

****************************************************************************************************

CSRF跨站请求伪造

不开启这个csrf会造成同一个浏览器打开多个页面,其他页面也能得到你网站的信息,csrf攻击(实际上是借助浏览器对认证过的网站假装是本人对服务器发送请求)

从springsecurity4.0开始默认开启了csrf保护,这个不对get请求进行防护,只对put,post,delete防护

而我在之前测试的时候关闭了这个防护。

.and().csrf().disable();//关闭csrf防护

需要引入thymeleaf模板引擎

<!--        引入Thymeleaf添加对springsecurity的标签支持-->
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity5</artifactId>
        </dependency>

在前端登录页加上(必须写在templates下,因为是thymeleaf)

<html lang="en" xmlns:th=" http://www.thymeleaf.org">添加th支持
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">

*********************************************************************************************************

微服务权限部分

单点登录

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值