SpringSecurity最新版从入门到精通,WebSecurityConfigurerAdapter已经过时?最新版来了。

这篇具有很好参考价值的文章主要介绍了SpringSecurity最新版从入门到精通,WebSecurityConfigurerAdapter已经过时?最新版来了。。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

spring security的超详细配置和使用攻略,包括从登录校验开始到不同页面、不同功能的权限管理,包括了整合thymeleaf框架、用户登录信息持久化处理、csrf防护等web安全。


一、SpringSecurity是什么?

SpringSecurity是SpringBoot支持的高度可自定义的安全框架,利用了SpringDI和SpringAOP的设计,提供了声明式安全访问控制功能,减少了大量为了安全配置所写的重复代码。

这里的安全主要是指用户权限管理,即不同的用户访问不同的页面和菜单,如果没有相关权限,则不能访问相关页面。

二、所需数据库设计

所有用户数据都是保存在数据库中,权限(角色)也应该保存在数据库中,用户与权限是多对多的关系,就需要一张中间表,所以现在需要三张表:用户表(user),权限表(role),权限用户中间表(role_user_link)。

web项目中,什么是权限的具体体现?就是各种url,不同的权限可以访问的url也不同,url与权限也是多对多的关系,所以又加了两张表:url表(url),url与权限中间表(role_url_link)。

基础需要一共是五张表:

websecurityconfigureradapter已过期,mybatis,java,spring boot,spring,web安全
但是一般用不到url表,暂时我是没有用到,所以还是基础用户角色三张表。

三、使用步骤

新建一个spring boot项目,导入基本的web、mysql、mybatis或mybatis-plus、thymeleaf、spring boot test、lombok等依赖,快速创建实体类、Dao和Service

1.添加依赖

代码如下(示例):

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2.创建SecurityConfig类

与之前的security教程,配置类会这样写:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {}

随着WebSecurityConfigurerAdapter的过时,创建SecurityConfig类也变得简单起来:

@EnableWebSecurity
@Configuration
public class SecurityConfig {}

就只是我们自己新建一个类,加上配置类注解就好,其中的方法下面会讲到。

3. 往配置类中加方法,实现登录验证

直接上代码:

@EnableWebSecurity
@Configuration
public class SecurityConfig {
	@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
   		httpSecurity.csrf().disable();
        httpSecurity.authorizeRequests()
                .anyRequest().authenticated()//所有请求,都需要登录状态校验
                .and()
                .formLogin();
        return httpSecurity.build();
    }
}

先将csrf(跨站请求攻击)关闭,后面会讲解如何配置。

往SecurityConfig类中添加上面的方法,并标注为Bean,即可实现简单的登录,即使自己没有写页面。

默认的url是 login,我们上面配置了拦截所有请求,所以输入任意url都会被拦截,然后跳到该登录页面。自带的页面,好像还不错:

websecurityconfigureradapter已过期,mybatis,java,spring boot,spring,web安全

SpringSecurity自带了登录页面,默认用户名为 username,密码在运行了项目后,会在控制台中打印出来,直接复制即可。
websecurityconfigureradapter已过期,mybatis,java,spring boot,spring,web安全
如果嫌麻烦,可以直接在application.yml中指定security默认的用户名和密码,但不建议这么做,因为这个用不到,毕竟用户数据要从数据库中取!

四、自定义登录功能—认证功能

这次要开始动真格的了,不仅要从数据库中取数据,还要走自己的登录页面并跳转到首页。

1.从数据库中获取用户数据

这个老生常谈,不知道在做项目的过程中做了多少次注册登录了。几乎都是从映射实体类、Dao层、Service层、Controller层等。

security要实现从数据库中获取用户数据也与以往步骤差不多,需要自己写Dao层,但只需要将查询到的用户实体对象交给SecurityService实现类即可,会自动走我们设定好的配置,不需要我们自己写controller了。

首先,新建一个SecurityService类,这个类需要实现UserDetailsService接口,然后需要实现其中的一个方法:

@Service
public class SecurityService implements UserDetailsService {
    private final UserService userService;

    public SecurityService(UserService userService) {
        this.userService = userService;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userService.getOne(new QueryWrapper<User>()
                .eq("username", username));
        
        if (user == null) {
            throw new UsernameNotFoundException("user is not found");
        }
        //return这么一长串是因为我的user实体类名字是User,与org.springframework.security.core.userdetails.User重名了
        return new org.springframework.security.core.userdetails.User(
                username,
                user.getPassword(),
                AuthorityUtils.commaSeparatedStringToAuthorityList("")//该参数暂时用不到,无意义,参数随便填
        );
    }
}

这里我为了偷懒使用的是mybatis-plus,总体逻辑便是从数据库中查出对应的user对象,并返回userDetails.User,切记不是直接返回实体类对象!

再次到登陆页面之后,会发现即使输入了正确的数据表中的用户名和密码,控制台会报错:
There is no PasswordEncoder mapped for the id “null”:

ERROR 24820 --- [nio-8080-exec-8] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception

java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

这是由于Security出于安全,需要将密码加密后比对。因此我们还需要在前面SecurityConfig类中配置密码加密器:

    /**
     * 密码加密器,会把客户端传来的密码进行加密,然后跟数据库中的密码做对比,要求数据库中的密码也是加密过的
     * 如果没有该加密器,spring security会报出异常:There is no PasswordEncoder mapped for the id "null"
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

再次登录,用户名密码正确,结果报出下面的异常Encoded password does not look like BCrypt

WARN 14588 --- [nio-8080-exec-4] o.s.s.c.bcrypt.BCryptPasswordEncoder     : Encoded password does not look like BCrypt

并且登录失败:
websecurityconfigureradapter已过期,mybatis,java,spring boot,spring,web安全
这是因为,程序内部使用的是加密后的密码与数据库中的明文密码进行比对,当然是错误的,这也是刚接触security常见的错误。解决方法有如下两种:
第一种(不推荐),在我们取出user对象后,在SecurityService中修改,userDetails.User传参的时候,将密码进行加密:

		//return这么一长串是因为我的user实体类名字是User,与org.springframework.security.core.userdetails.User重名了
        return new org.springframework.security.core.userdetails.User(
                username,
                new BCryptPasswordEncoder().encode(user.getPassword()),
                AuthorityUtils.commaSeparatedStringToAuthorityList("")//无意义,参数随便填
        );

第二种,在数据库中存储的密码就是加密后的密码。

这里要求整个项目中注册修改密码后都是存储密文,那我们做demo的数据还是来自我们自己添加,一个个做单元测试,输入明文后再复制密文到数据库也是一个获取密文可行的方法。

这里推荐一个网站,可以获取多种加密方式的密文:
在线加密

在做单元测试时发现,相同的明文每次加密密文都不同,但依旧能验证成功,这里推荐一个文章,感兴趣的朋友可以去看看:为什么密文不同还能比对成功

2. 自定义登录页面

要使用自己写的登录页面,只需要如下几步即可:

  1. 在templates文件夹下添加自己的登录页面
  2. 在Controller层中配置登录页面跳转显示逻辑
  3. 在SecurityConfig类中做相关配置即可

SecurityConfig配置类中的代码如下:

	httpSecurity.formLogin()
                .loginProcessingUrl("/toLogin")
                .loginPage("/myLogin")

loginProcessingUrl代表的是页面中form表单的action,一旦接收到该url,就会跳转到登陆页面。
loginPage代表的是我们自定义的登陆页面。当然不要忘记了在controller中配置。

3. 登录成功后逻辑

登陆成功后一般就要跳转到别的页面,security提供了三个登录成功后的跳转方式,分别是:

httpSecurity.formLogin()
            .defaultSuccessUrl()//默认
            .successForwardUrl()//成功后跳转
            .successHandler()//可选默认,也可自定义的

① defaultSuccessUrl(“/url”, alwaysUse)

defaultSuccessUrl有两个实现,一个只需要一个url参数,另一个还要一个boolean类型的参数。

defaultSuccessUrl默认登录成功后重定向,如果alwaysUse参数设置为false,则会跳转到登录前的页面,而不是url参数的页面。设置为true则会强制为url参数页面。不写为false。

② successForwardUrl(“/url”)

successForwardUrl登录成功后内部请求转发,url地址不会变,所以会显示form的action,即loginProcessingUrl拦截的地址。

③ successHandler()

如果参数是:new ForwardAuthenticationSuccessHandler("/index")登录成功后会是内部请求转发,与successForwardUrl()相同。但可以自定义实现了AuthenticationSuccessHandler接口的类,然后实现重定向,如:

public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    private final String url;

    public MyAuthenticationSuccessHandler(String url) {
        this.url = url;
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        response.sendRedirect(url);
    }
}

使用自定义参数:

.successHandler(new MyAuthenticationSuccessHandler("/index"))

4. 登录失败后逻辑

与登录成功类似,登录失败也有三个类似的处理方式:

httpSecurity.formLogin()
                .failureUrl()
                .failureForwardUrl()
                .failureHandler()

主要讲一下failureUrlfailureForward的区别和使用注意事项:
① failureUrl

与defaultSuccessUrl类似,是通过重定向的方式进行跳转。

但是由于是失败后的跳转,是连最基本的登录认证都没有通过的,所以是没有任何权限的,如果重定向的页面有权限限制则会因为没有权限而回到登录页面,这点需要格外注意。

② failureForwardUrl

与successForwardUrl类似,是通过服务器内部转发来实现跳转的不再多说。

③ failureHandler()

与successHandler类似,不再赘述。

5. 自定义表单的键名

登录功能数据来源于前端页面发送来的表单数据,SpringSecurity默认的键名(form表单中name属性)分别是:username和password。

如果想要使用自定义键名,只需要在前端表单写好后,再在SecurityConfig中添加如下代码即可:

				.usernameParameter("username")
                .passwordParameter("password")

这里的username和password就可以改为你自定义的键名。

6. rememberMe功能

rememberMe顾名思义就是记住我功能,要开启此功能只需要在securityConfig配置类中添加代码即可:

	httpSecurity.rememberMe()
                .tokenValiditySeconds(60*60*24*14)//cookie过期时间,单位秒,默认2周,过期后数据库中的记录并不会删除。
                .rememberMeCookieName("rememberMe")
                .userDetailsService(securityUserDetailsService)//登录逻辑交给哪个对象
                .tokenRepository(persistentTokenRepository)//持久层对象
                .rememberMeParameter("rememberMe")

下面逐个了解分别配置了什么东西。

  • rememberMe()代表开启了rememberMe功能
    rememberMe的原理是将一个名为remember-me的cookie存储在浏览器中,默认时长两周,后续访问都会先去cookie中去找。

  • tokenValiditySeconds()设置cookie保存时间
    cookie过期时间,单位秒,默认2周,过期后数据库中的记录并不会删除。

  • rememberMeCookieName()设置cookie的名字,默认为remember-me

  • .userDetailsService(securityUserDetailsService)//登录逻辑交给哪个对象
    .tokenRepository(persistentTokenRepository)//持久层对象

    这两个是重点,cookie保存在浏览器并不安全,有时还会被删除,因此应该利用持久层,将登录信息和用户数据保存在数据库中。

    security就提供了这样的功能,只需要在SecurityConfig类中添加持久层的相关配置,即可自动在数据库中建立表和插入数据。

    一切不用自己动手,只需要做做配置,security便会自动执行这一切。
    在配置类中添加如下代码:

@Bean
    public PersistentTokenRepository persistentTokenRepository(DataSource dataSource) throws SQLException {
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
        jdbcTokenRepository.setDataSource(dataSource);
        //根据表名查找表
        ResultSet resultSet = Objects.requireNonNull(jdbcTokenRepository.getDataSource()).getConnection().getMetaData().getTables(null, null, "persistent_logins", new String[]{"TABLE"});
        //如果已经存在则跳过,如不存在则创建
        if (resultSet == null || !resultSet.next()) {
            jdbcTokenRepository.setCreateTableOnStartup(true);
        }
        return jdbcTokenRepository;
    }

然后利用spring的自动注入实例化persistentTokenRepository,再在需要的地方使用。
构造器注入:

private final PersistentTokenRepository persistentTokenRepository;
public SecurityConfig(PersistentTokenRepository persistentTokenRepository) {
        this.persistentTokenRepository = persistentTokenRepository;
    }

需要注意的是,由于关于persistentTokenRepository的Bean是直接写在该配置类中的,如果要在该配置类中自动注入自己的类,会有循环依赖的问题,所以需要在构造器的参数上加上@Lazy注解:

private final PersistentTokenRepository persistentTokenRepository;
public SecurityConfig(@Lazy PersistentTokenRepository persistentTokenRepository) {
        this.persistentTokenRepository = persistentTokenRepository;
    }

循环依赖可以参考这篇文章:循环依赖问题

配置好以后,启动项目就会自动检查数据库中是否有名为persistent_logins的表,如果没有则会自动创建,如果有,则会跳过创建。

表中的数据即使用户信息过期了,也不会删除。
如果未过期,则更新最近登陆时间。
如果过期了再登录会新插入一条记录。

  • rememberMeParameter()设置rememberMe的参数名,要与前端checkBox的name一致。

7. 退出登录功能

退出功能的配置代码如下:

	httpSecurity.logout()//会清除rememberMe该用户的登录记录
                .logoutUrl("/exit");//要与前端退出登录的url一致

如果开启了rememberMe功能,并且配置了持久层连接数据库,那么退出登录时会将该用户的记录全部删除,无论是过期还是未过期的记录。

logout的其余配置,包括退出成功后、退出失败后等等与登录的配置大同小异,这里不再赘述。

五、授权功能

1. 取得用户角色和权限

还记得在前面4.1中的SecurityService中根据用户名字获取user对象并返回UserDetails的方法吗?

//return这么一长串是因为我的user实体类名字是User,与org.springframework.security.core.userdetails.User重名了
       return new org.springframework.security.core.userdetails.User(
                username,
                user.getPassword(),
                AuthorityUtils.commaSeparatedStringToAuthorityList("")//该参数暂时用不到,无意义,参数随便填
        );

其中返回的对象中有个参数是 AuthorityUtils.commaSeparatedStringToAuthorityList("") ,当时用不到所以是无意义的,现在权限校验需要用到了。

首先,我们从数据库中获取到user对象后,可以根据userId查找role_user_link表找到roleId,再根据roleId找到role。注意到该参数是一个集合,所以查找结果应该是个List<\String>,即使一个用户可能只有一个角色。

根据数据库设计不同,可能是权限与用户绑定,那么一个用户就可以有多个权限,使用List<\Strign>是不是就合理多了?

当然也有的数据库设计,既有角色,又有权限,即:用户表、用户角色中间表、角色表、角色权限中间表、权限表。这样可以即查出角色又查出权限,然后一起塞到AuthorityList中。

下面是完整的SecurityService类:

@Service
public class SecurityService implements UserDetailsService {
    private final UserService userService;
    private final RoleUserLinkService roleUserLinkService;
    private final RoleService roleService;

    public SecurityService(UserService userService, RoleUserLinkService roleUserLinkService, RoleService roleService) {
        this.userService = userService;
        this.roleUserLinkService = roleUserLinkService;
        this.roleService = roleService;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userService.getOne(new QueryWrapper<User>()
                .eq("username", username));

        if (user == null) {
            throw new UsernameNotFoundException("user is not found");
        }

        List<String> roles = new ArrayList<>();
        roleUserLinkService.listObjs(new QueryWrapper<RoleUserLink>()
                .select("role_id")
                .eq("user_id", user.getId()))
                .forEach(roleId -> roles.addAll(roleService.listObjs(new QueryWrapper<Role>()
                        .select("role")
                        .eq("id", roleId)).stream().map(Object::toString).collect(Collectors.toList())));

        List<SimpleGrantedAuthority> authorityList = new ArrayList<>();
        //这里其实是权限,而不是角色
        roles.forEach(role -> authorityList.add(new SimpleGrantedAuthority(role)));
        //角色应该这样写,我这里没有权限,只有角色。所以就都添加了,去掉ROLE_就是一样的
        roles.forEach(role -> authorityList.add(new SimpleGrantedAuthority("ROLE_" + role)));

        //return这么一长串是因为我的user实体类名字是User,与org.springframework.security.core.userdetails.User重名了
        return new org.springframework.security.core.userdetails.User(
                username,
                //在线BCrypt加密 https://www.bejson.com/encrypt/bcrpyt_encode/
                user.getPassword(),
                authorityList
        );
    }
}

我的数据库设计是三张表,即:用户表、角色表、中间表。所以角色充当了权限和角色两种。

从代码可见,anthorityList.add()中针对角色有特定的前缀:“ROLE_”,如果要插入role,想要按照role进行验证,这个前缀是必须的。

2. 配置校验规则

现在我们已经取到了登录用户的角色和权限信息,下面就是去配置类中指定哪些url需要哪些权限或角色才能访问:

httpSecurity.authorizeRequests()
                .antMatchers("/myLogin").permitAll()//myLogin所有人都可以访问
                .antMatchers("/index").permitAll()
                .antMatchers("/studentIndex").hasAnyRole("student", "admin")//按照角色校验,但是不加 ROLE_ 的前缀,双引号
                .antMatchers("/teacherIndex").hasAnyAuthority("teacher", "admin")//按照权限校验,双引号
                .antMatchers("/adminIndex").hasAnyAuthority("admin")
                .antMatchers("/teacherIndex").access("@myPowerServiceImpl.isPowerEnabled(request, authentication)")//自定义拦截,参数只能写request,不能写httpServletRequest,不知道为什么,也不知request哪里来的
                .anyRequest().authenticated()//其他请求需要登录状态校验
  1. authorizeRequests()开启对request的验证
  2. antMatchers()指定要验证的url,后面跟上对该url的验证规则
  3. permitAll()表示该url所有人都可以访问,一般用于公共页面,登录、首页、错误等
  4. hasAnyRole、hasRole:该url只有这些角色才能访问,不同的是anyRole后面可以跟多个角色,role后面只能跟一个角色。这里角色不必加我们获取到角色时添加的前缀ROLE_。
  5. hasAnyAuthority、hasAuthority:该url只有拥有这些权限才能访问,any带与不带的区别同上。
  6. access()下面会讲到
  7. anyRequest():其他请求
  8. authenticated():处于登陆状态即可访问

所以上述代码翻译为人话就是:

myLogin、index所有人都可以访问,无论登不登陆;
studentIndex 角色为 student 和 admin 可以访问;
teacherIndex 角色为 teacher 和 admin 可以访问;
adminIndex 角色为 admin 可以访问;
其他请求,只要成功登录了就可以访问。

3. 自定义拦截规则

有的项目中会要求权限模糊校验,与权限对比有一部分通过校验即可访问,比如:有权限名为 class:manger:student,项目要求只要有class就可以通过校验。
这个例子尽管不恰当,但这种要求可以通过自定义access()中的参数实现:
我们先定义一个接口类

public interface MyPowerService {
    Boolean isPowerEnabled(HttpServletRequest request, Authentication authentication);
}

然后实现它:

@Service
public class MyPowerServiceImpl implements MyPowerService {
    @Override
    public Boolean isPowerEnabled(HttpServletRequest request, Authentication authentication) {
        Object user = authentication.getPrincipal();
        if (user instanceof UserDetails) {
            UserDetails userDetails = (UserDetails) user;
            Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
            //角色需要写ROLE_,权限不用,我这里没有权限,只有角色。所以就都添加了,去掉ROLE_就是一样的
//            boolean enabled1 = authorities.contains(new SimpleGrantedAuthority("ROLE_student"));
            boolean enabled2 = authorities.contains(new SimpleGrantedAuthority("teacher"));
            boolean enabled3 = authorities.contains(new SimpleGrantedAuthority("ROLE_admin"));

            return enabled2 || enabled3;
        }
        return false;
    }
}

然后再access()中通过@调用即可:

.antMatchers("/teacherIndex").access("@myPowerServiceImpl.isPowerEnabled(request, authentication)")//自定义拦截,参数只能写request,不能写httpServletRequest,不知道为什么,也不知request哪里来的

注意isPowerEnabled()中的第一个参数,虽然实现类中定义时是httpservlet,但是只能写request

4. 通过注解方式实现授权

如果觉得上面的方式过于麻烦,且写起来又臭又长,那么下面就是喜闻乐见的注解方式了。

使用注解的方式添加授权的步骤如下:

  1. 在SpringBoot启动类上添加如下注解,开启注解校验功能:
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true)
  1. 在controller层的请求处理方法上面按照格式添加注解即可,例如:
@Secured({"ROLE_student","ROLE_admin"})//作用相当于SecurityConfig中的securityFilterChain中的hasAnyRole,但是需要加ROLE_
    @RequestMapping("/studentIndex")
    public String studentIndex() {
        return "student/studentIndex";
    }

    @Secured({"ROLE_teacher","ROLE_admin"})
    @PreAuthorize("hasAnyAuthority('teacher', 'admin')")//作用相当于SecurityConfig中的securityFilterChain中的hasAnyAuthority,但里面是单引号
    @RequestMapping("/teacherIndex")
    public String teacherIndex() {
        return "teacher/teacherIndex";
    }

    @Secured({"ROLE_admin"})
    @PreAuthorize("hasAnyAuthority('admin')")//在进行操作前就拦截
//    @PostAuthorize("hasAnyAuthority('admin')")//在进行操作后才进行校验
    @RequestMapping("/adminIndex")
    public String adminIndex() {
        return "admin/adminIndex";
    }

注解格式介绍:

  1. @Secured({“ROLE_student”,“ROLE_admin”})
    跟SecurityConfig类中的hasAnyRole很像,只是hasAnyRole()参数不必加"ROLE_"前缀。
  2. @PreAuthorize(“hasAnyAuthority(‘teacher’, ‘admin’)”)
    作用相当于SecurityConfig中的securityFilterChain中的hasAnyAuthority,但里面是单引号
  3. @PostAuthorize(“hasAnyAuthority(‘admin’)”)
    作用相似于SecurityConfig中的securityFilterChain中的hasAnyAuthority,但里面是单引号
  4. @PreAuthorize和@PostAuthorize的区别
    @PreAuthorize是在执行处理请求的方法之前进行授权校验,如果不通过则不会执行方法。
    @PostAuthorize则是在执行过方法之后才进行权限校验,如果不通过则不会有反馈,一般用于特殊需求。

六、CSRF跨站伪造请求攻击防护

1. 什么是跨站伪造请求攻击?

websecurityconfigureradapter已过期,mybatis,java,spring boot,spring,web安全
用户在客户端浏览器访问A站,保存登陆信息后,又去浏览网站B,网站B偷偷获取cookie中的用户信息,然后拿着该信息去访问网站A,这个过程用户并没有在网站A做任何操作,一系列操作都是网站B拿着用户信息去伪造的,这就是跨站伪造请求攻击。

2. csrf原理

  • 既然网站B只能获取到cookie的值,用户操作的时候一定是停留在网站网页上的,所以csrf的原理就是在请求中添加一个taken,只有taken和cookie同时符合的时候才能访问页面。

  • 网站B只能获取cookie中的值,不能获取页面的值,该taken也不能让用户看到,所以前端控件属性应该是hidden的。

3. csrf的使用

csrf的前端taken格式部分较为固定:

<form method="post" id="userForm" action="/toLogin"><!-- action都会被拦截 -->
    <input type="hidden" name="_csrf" th:if="_csrf" th:value="${_csrf.token}"><!-- 每个需要做验证的页面都要写 -->
  <label>
    账号:<input type="text" name="username"/>
  </label>
  <label>
    密码:<input type="password" name="password"/>
  </label>
    <label>
        <input type="checkbox" name="rememberMe" value="true"/>记住我?
    </label>
    <button type="submit" name="login">登录</button>
</form>

其中name固定为 _csrf,搭配thymeleaf使用。
后端:仅需这一句即可:

httpSecurity.csrf();

如果开启了该功能,几乎每个页面都必须有这样的一个存储taken的地方,否则会报出权限不足的异常。

总结

本文仅仅简单介绍了SpringSecurity的使用。
第一次写,如有错误欢迎指出,欢迎给出宝贵的建议和意见。文章来源地址https://www.toymoban.com/news/detail-643830.html

到了这里,关于SpringSecurity最新版从入门到精通,WebSecurityConfigurerAdapter已经过时?最新版来了。的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Flutter入门教程(一),2023最新版包含安装,初始化!简单易懂!

    首先,在一切的开始之前我们来介绍一下什么是Flutter,Flutter 是一个由 Google 开发的开源移动应用程序开发框架,可以让开发者使用单一代码库构建高质量的、高性能的 Android 和 iOS 应用程序。Flutter 的主要优势之一是其快速的开发周期,因为它使用了热重载技术,这意味着开

    2024年02月16日
    浏览(52)
  • 【2023年最新版考试真题分享】 Apsara Clouder云计算专项技能认证:云服务器ECS入门【已通过】

    考试入口:https://edu.aliyun.com/certification/cldc15 【需要自己注册阿里云账户,并实名认证】 考试一共20道题,时长30分钟 本次考题如下,答案仅供参考:

    2024年02月16日
    浏览(72)
  • 【最新版配置conda环境】新版pycharm导入新版anaconda环境

    最近下载了新版pycharm和新版anaconda,并且在命令行创建了环境,想着在pycharm里面导入环境。结果现在的导入方式发生了变化。 之前是通过导入Python.exe进行的。 现在: 当我们点击进去之后,会发现找不到python.exe了。 具体什么原因我不知道,应该是版本问题。 解决方法: 通

    2024年02月08日
    浏览(53)
  • 抖音协议最新版

    抖音核心协议的步骤是 : 1、在查询串插入一个固定的键rstr 2、对查询串进行按键排序并取值,对空格和+进行转义为a 3、然后取MD5;如果时间轴1为1,那么取多一次MD5 4、将MD5结果分别和5******6、1******4进行2次错位排序算法 5、将4的结果再进行一次错位排序,得到26位字符 6、

    2024年02月13日
    浏览(45)
  • 淘宝协议最新版

    我可以为您提供一些示例代码,以演示一些与电商平台相关的功能。请注意,以下代码仅为示例,具体实现还需要根据您的应用程序的架构、技术栈和需求进行调整和扩展。 1. 用户注册功能:    - 后端实现:在后端,您可以创建一个用于处理用户注册请求的接口。当用户提

    2024年02月06日
    浏览(51)
  • 微信小程序新版隐私协议弹窗实现最新版

    2023.08.22更新:【原文连接】 以下指南中涉及的 getPrivacySetting、onNeedPrivacyAuthorization、requirePrivacyAuthorize 等接口目前可以正常接入调试。调试说明: 在 2023年9月15号之前,在 app.json 中配置 __usePrivacyCheck__: true 后,会启用隐私相关功能,如果不配置或者配置为 false 则不会启用。

    2024年02月10日
    浏览(72)
  • 小红书协议算法最新版

    如果您想通过学习来了解小红书的点赞、关注、私信等功能的实现,以下是一些一般性的思路和示例代码,供您学习参考: 1. 点赞功能:    - 后端实现:在后端,您可以创建一个用于存储用户点赞信息的数据库表。对于每个帖子或内容,可以创建一个对应的点赞表,记录用

    2024年02月06日
    浏览(40)
  • 抖音协议算法最新版

    抖音的协议算法是指用于推荐内容和个性化用户体验的算法系统。这些算法根据用户的兴趣、行为和偏好来推荐适合他们的视频内容,以提供更好的用户体验。 抖音的协议算法使用了大量的数据和机器学习技术来实现个性化推荐。以下是一些可能应用于抖音协议算法的技术和

    2024年02月06日
    浏览(46)
  • composer最新版本安装

    安装前请务必确保已经正确安装了 PHP。打开命令行窗口并执行  php -v  查看是否正确输出版本号。 打开命令行并依次执行下列命令安装最新版本的 Composer: 复制 复制 复制 执行第一条命令下载下来的  composer-setup.php  脚本将简单地检测  php.ini  中的参数设置,如果某些参

    2024年02月13日
    浏览(47)
  • 快速安装最新版Docker

    安装docker 列出系统中以安装的docker包: 卸载以安装的docker包 如果系统中没有docker,则直接进行下一步 安装docker所需依赖:  添加docker的yum源: yum安装docker: 验证docker版本以确认安装成功: 如图所示,docker安装成功 启动docker 执行以下命令启动docker: 然后将docker设置为开机

    2024年02月12日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包