SpringSecurity安全授权

目录

前言

正文

1.基本流程

2.基本用法

3.配置项 

4.HttpSecurity 方式和内存认证方式 

5.认证流程

6.基于数据库查询的登录验证

7.多种角色权限认证 

8.自定义权限认证 

总结


前言

安全对于任何系统来说都是非常重要的,权限的分配和管理一直都是开发者需要特别重视的。一旦缺乏基本和有力的授权验证,一些别有用心之人就会利用这个漏洞对开发者的 Web 应用或者其他软件进行不法侵害。Spring Boot 技术中有许多优秀的安全框架和认证授权方案,本次将介绍比较流行的框架技术 Spring Security 及其实践应用。


正文

Spring Security 是 Spring Boot 中一款功能强大基于 Spring 的企业级应用的提供安全访问权限的安装框架,在实际工程项目中也会经常用到。通过依赖注入的方式,可以使用 Spring Security 库提供声明式的安全访问控制功能。它和 Spring Boot 以及其他 Spring 模块紧密相连。

1.基本流程

Spring Security 的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器。 

图中只展示了核心过滤器,其它的非核心过滤器并没有在图中展示

  • UsernamePasswordAuthenticationFilter:负责处理我们在登页面填写了用户名密码后的登陆请求。入门案例的认证工作主要有它负责。
  • ExceptionTranslationFilter: 外理过滤器中抛出的任 AccessDeniedException 和 AuthenticationException。
  • FilterSecuritylnterceptor: 负责权限校验的过滤器 

通过 debug 查看当前的过滤器链

package org.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class Main {
    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(Main.class, args);
        System.out.println(run);//在此处打上断点
    }
}

打开表达式计算面板 

run.getBean(DefaultSecurityFilterChain.class)

计算求值:

2.基本用法

安装,在 pom.xml 中导入依赖即可

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

在项目中编写一个测试的接口 /testHi,代码如下:

package org.example.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HiController {
    @GetMapping("/hi")
    public String hi(){
        return "Hi";
    }
}

编写一个类,更好的配置管理。

package org.example.config;

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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * Security 配置类
 */
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     *  认证
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .passwordEncoder(new BCryptPasswordEncoder())
                .withUser("freejava")
                .password(new BCryptPasswordEncoder().encode("123456"))
                .roles("VIP1");
    }

    /**
     * 授权
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //设置匹配的资源白名单访问
        http.authorizeRequests().antMatchers("/","/asserts/**",
                "/pages/login.html","/userlogin")
                .permitAll()
                .antMatchers("/level1/**").hasRole("VIP1")
                .antMatchers("/level2/**").hasRole("VIP2")
                .antMatchers("/level3/**").hasRole("VIP3")
                .anyRequest().authenticated();//剩余任何资源必须认证
        //开启登录页
        http.formLogin();
        //开启自动注销
        http.logout().logoutSuccessUrl("/login");//注销之后来到登录页
        http.csrf().disable();
    }
}

最后运行会出现如下界面:

3.配置项 

如果想要修改默认的账号和密码,可以在 application.properties 文件中加入下面的配置项。

spring.security.user.name=freejava
spring.security.user.password=123456
spring.security.user.roles[]=admin

4.HttpSecurity 方式和内存认证方式 

所谓内存认证就是自定义配置类,该配置类继承 WebSecurityConfigurerAdapter,需要实现一些自定义配置和方法,具体代码如下:

package org.example.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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@EnableWebSecurity
public class RealSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    PasswordEncoder passwordEncoder(){
        //NoOpPasswordEncoder  在高版本的Spring Boot 中已被弃用,不建议使用
        return new BCryptPasswordEncoder();
    }

    @Autowired PasswordEncoder passwordEncoder;
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .passwordEncoder(passwordEncoder)//使用对应的加密
                .withUser("admin")
                .password(passwordEncoder.encode("123456"))//使用对应的解密
                .roles("ADMIN","USER")
                .and()
                .withUser("freephp")
                .password(passwordEncoder.encode("123456"))
                .roles("USER");
    }
}

上面这段代码中,inMemoryAuthentication 代表把这个配置保存在内存中,然后使用 withUser 方法增加授权账号,用 password 方法设置密码,用 roles 来设置账号所属的权限群组。

HttpSecurity 是另外一种认证方式,也是使用 configure 方法,具体代码如下:

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**")
                .hasRole("ADMIN")
                .antMatchers("/user/**")
                .access("hasAnyRole('ADMIN','USER')")
                .anyRequest()
                .authenticated()//任意登录的用户都可以访问
                .and()
                .formLogin()
                .loginProcessingUrl("/login")
                .permitAll()
                .and()
                .csrf()
                .disable();
    }

使用 andMatcher 设置需要被授权的 URL 路径,access 方法给予某些角色访问权限,代码如下:。

package org.example.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SwagController {
    @GetMapping("/user/sayHi")
    public String myUser(){
        return "Hi,user";
    }
    
    @GetMapping("/admin/hello")
    public String admin(){
        return "admin page";
    }
    
    @GetMapping("/hello")
    public String hello(){
        return "hello,man";
    }
}

运行项目后,访问 http://localhost:8080/admin/hello, 则会要求输入账号和密码,使用 admin 账号,密码输入 123456,即可进入后台 /admin/hello 页面,如图。

5.认证流程

  • Authentication接口: 它的实现类,表示当前访问系统的用户,封装了用户相关信息。
  • AuthenticationManager接口: 定义了认证Authentication的方法。
  • UserDetailsService接口: 加载用户特定数据的核心接口。里面定义了一个根据用户名查询用户信息的方法。
  • UserDetails接口: 提供核心用户信息。通过UserDetailsService根据用户名获取处理的用户信息要封装成UserDetails对象返回,然后将这些信息封装到Authentication对象中。

所以接下来如果要使用数据库做登录验证,只要把实现类 InMemoryUserDetailsManager 做一个替换,DaoAuthenticationProvider 调用自定义的实现类。让其不再使用内存做认证进入数据库查询,实现 UserDetailsService 接口即可。

6.基于数据库查询的登录验证

之前都是使用内存来存储认证数据,其实可以考虑使用数据库进行持久化数据存储。这样更加方便进行账号管理,也更符合实际项目开发的需求。 

创建一个 roles 库,然后创建用户表、角色权限表、用户和角色权限关系表。

create database     r_security;
use r_security;
-- 用户表
CREATE TABLE  `r_users`(
    `id` int(11) unsigned NOT NULL AUTO_INCREMENT primary key COMMENT '主键',
    `username` varchar(50) not null  comment '账号名',
    `password` varchar(300) not null comment '密码',
    `status` tinyint(11) not null comment '账号状态,1:正常、2:被封',
    `created` int (11) not null comment '创建时间,时间戳'
    );
-- 角色权限表
create table `r_roles`(
    `id` int(11) unsigned not null auto_increment comment '主键',
    `name` varchar(50) not null  comment '角色名',
    `permission_path` varchar(500) not null  comment '权限路径,如/admin/*',
    primary key (id)
);
-- 用户角色权限关系表
create table `r_user_roles`(
    `id` int(11) unsigned not null auto_increment comment '主键',
    `user_id` int(11) unsigned not null  comment '用户ID',
    `role_id` int(11) unsigned not null comment '角色ID',
    primary key (`id`),
    key `user_id` (`user_id`),
    key `role_id` (`role_id`),
    constraint `role_id` foreign key  (`role_id`) references `r_roles`(`id`) on
                           delete  restrict ,
    constraint `user_id` foreign key (`user_id`) references `r_users`(`id`) on
                           delete  restrict
)

为了方便测试,先插入几条测试数据,r_users 的数据如图

R_roles的数据如图,插入三条数据,有三种角色,一是管理员角色,二是 root 权限,也就是超级管理员。三是 dba,数据管理员。这三种角色可以访问不同的 URL。 

用户角色表中插入数据

为了生成上面 r_users 表中加密后的密码,攥写了使用 Bcrypt 加密的程序,代码如下: 

import java.util.ArrayList;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
public class BcryptTest {
    public static void main(String[] args) {
        ArrayList<String> passwordArr = new ArrayList<>();
        passwordArr.add("123456");
        getUsersEncodePasswords(passwordArr);
    }

    private static void getUsersEncodePasswords(ArrayList<String> passwordArr) {
        for (String pass :passwordArr){
            //密码加密
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            String newPassword = passwordEncoder.encode(pass);
            System.out.println(" 原始密码是:"+pass+",加密密码为:"+newPassword);
            //对比这两个密码是不是同一个密码
            boolean match = passwordEncoder.matches(pass,newPassword);
            System.out.println("两个密码一致:"+match);
        }
    }
}

运行结果如图:

Bcrpt 加密算法非常安全,此算法自身实现了随机盐生成,很难被逆向破解。 

创建一个新的项目,导入依赖,pom.xml代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>Security2</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--     引入security依赖   -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

r_roles 表对应的部分实体类对象

package org.example.entity;

import lombok.Data;

@Data
public class Role {
    // 主键 ID
    private Integer id;
    // 名称
    private String name;
    //权限路径
    private String permission_path;
}

创建 r_users 对应的 POJO 对象 User,继承自 UserDetails 接口,代码如下:

package org.example.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements UserDetails {
    //主键 id
    private Integer id;
    //用户名
    private String username;
    //密码
    private String password;

    // 状态 1:正常,2:封禁
    private int status;

    // 创建时间
    private int created;

    private List<Role> roles;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for(Role role : roles){
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }
        return authorities;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return status != 2;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return status == 1;
    }
}

Java 类 User 实现了 Spring Security 中的 UserDetails 接口,这是因为 Spring Security 需要具体的用户信息来进行认证和授权。通过实现 UserDetails 接口,User 类可以与 Spring Security 框架集成,允许 Spring Security 使用该类的实例来获取用户的安全相关信息。

  • getAuthorities():返回授予用户的权限列表。在这个 User 类中,它遍历用户的角色列表 roles 并为每个角色创建一个 SimpleGrantedAuthority 对象,最终返回权限集合。
  • getPassword():返回用户的密码。在这个 User 类中,这个方法返回 User 对象的 password 字段。
  • getUsername():返回用户的用户名。在这个 User 类中,这个方法返回 User 对象的 username 字段。
  • isAccountNonExpired():检查用户的账户是否已过期。在这个 User 类中,这个方法硬编码返回 true,这意味着账户被认为永远不会过期,在数据库设计中没有该字段,所以默认返回 true。在实际的应用程序中,你可能需要添加一些逻辑来判断账户是否真的过期了。
  • isAccountNonLocked():检查用户是否未被锁定,返回 false 代表被锁定,true 没有被锁定。
  • isCredentialsNonExpired():检查用户证书(密码)是否未过期。在这个 User 类中,这个方法返回 true,表明证书永远不会过期。但在实际应用中,你可能会根据业务逻辑添加相应的实现代码。
  • isEnabled():检查用户是否被启用。在这个 User 类中,如果 status 字段的值为 1,代表用户状态正常,方法返回 true;否则返回 false。

Mapper 的编写如下:

package org.example.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.example.entity.Role;
import org.example.entity.User;

import java.util.List;

@Mapper
public interface Usermapper {
    @Select("select * from r_roles as r join r_user_roles as ur on r.id = ur.user_id where ur.user_id = #{id}")
    List<Role> getUserRoleByUserId(Integer id);
    @Select("select * from r_users where username = #{username}")
    User getUserByUsername(String username);
}

UserService 如下:

package org.example.service;

import org.example.entity.User;
import org.example.mapper.Usermapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class UserService implements UserDetailsService {
    @Autowired
    private Usermapper usermapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = usermapper.getUserByUsername(username);
        if (user == null){
            throw new UsernameNotFoundException("该账户不存在");
        }
        //根据 user id 获取用户的角色信息
        user.setRoles(usermapper.getUserRoleByUserId(user.getId()));
        return user;
    }
}

UserService 类实现了 Spring Security 中的 UserDetailsService 接口,这个接口主要用于在认证过程中通过用户名查找用户及其权限。在 loadUserByUsername 方法中,你使用了 Usermapper 来获取具体的 User 对象以及相关的角色信息。 

为了测试方便编写 controller:

package org.example.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {
    @GetMapping("/dba/hi")
    public String dba(){
        return "Hi,dba page";
    }
    
    @GetMapping("/user/hi")
    public String user(){
        return "Hi,user";
    }
    @GetMapping("/admin/hi")
    public String admin(){
        return "Hi,admin";
    }
    @GetMapping("/test/Hi")
    public String testHi(){
        return "Hi,just for test";
    }
}

最后对Spring Security 进行配置编写,代码如下: 

package org.example.config;

import org.example.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.access.AccessDeniedException;
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.EnableWebSecurity;
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.access.AccessDeniedHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    UserService userService;
    @Autowired
    PasswordEncoder passwordEncoder;

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/bda/**")
                .access("hasAnyAuthority('dba','admin','root')")
                        //"hasAnyRole('dba','admin','root')")  会自动拼接头,Role_为头加上对应权限
                .antMatchers("/admin/**").access(
                        "hasAnyAuthority('root','admin')")//不会拼接头,直接认证。
                .and()
                .formLogin()
                .loginProcessingUrl("/login")
                /*.and()
                .anonymous()//未登录才可以访问 permitAll 所有都可以访问*/
                .and().csrf().disable();
        http
                //访问被拒绝走以下
                .exceptionHandling()
                .accessDeniedHandler(new AccessDeniedHandler() {
                    @Override
                    public void handle(HttpServletRequest request,
                                       HttpServletResponse response,
                                       AccessDeniedException accessDeniedException)
                            throws IOException, ServletException {
                        // 自定义响应逻辑
                        response.sendRedirect("/access-denied");
                    }
                });
        //如果需要跨域使用这里,并配置spring WebMVCconfig
        http.cors();
    }
}

成功 

7.多种角色权限认证 

有时候一个账号的权限可能是多个,如 freejava 即使 admin 又是 dba。那么在配置中可以增加显示权限包含关系的代码,可以在 Spring Secuirty 中配置代码如下: 

    @Bean
    RoleHierarchy roleHierarchy(){
        RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
        String hierarchy = "ROLE_dba > ROLE_user ROLE_admin > ROLE_dba";
        roleHierarchy.setHierarchy(hierarchy);
        return roleHierarchy;
    }

该配置生效后,具有 ROLE_admin 的角色的用户可以访问所有资源,而 ROLE_dba 的角色用户可以访问自身权限的资源和 ROLE_user 的角色的用户资源。 

8.自定义权限认证 

如果我们不想使用默认提供的权限认证,或面对复杂的业务需要时,可能需要采取自定义认证方式实现权限认证。

自定义一个类

package org.example.expression;

import org.example.entity.Role;
import org.example.entity.User;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component("ex")
public class U_Define_Expression {


    public boolean hasAutority(String authority){
        //获取当前用户的权限
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        User LoginUser = (User) authentication.getPrincipal();
        List<Role> roles = LoginUser.getRoles();
        List<String> permissions = new ArrayList<>();
        for(Role role :roles){
            permissions.add(role.getName());
        }
        //判断用户权限集合中是否存在 authority
        return permissions.contains(authority);
    }
}

在需要使用的 controller 前加上 @PreAuthorize("@ex.hasAutority('dba')") 表示访问前的验证

补充 

HttpSecurity 是 Spring Security 的关键部分,用于配置 Web 安全性的详细内容。以下是在 Spring Security 中常用的 HttpSecurity 方法的概览:

  • authorizeRequests():开始请求级安全配置,允许你指定 URL 访问规则。

  • antMatchers(String... antPatterns):使用 Ant 风格的路径模式定义安全限制。

  • access(String):设置访问特定路径所需的权限表达式。

  • hasAuthority(String)hasAnyAuthority(String...):指定用户必须具有的权限以访问特定路径。

  • hasRole(String)hasAnyRole(String...):指定用户必须具有的角色才能访问特定路径。这通常自动添加 “ROLE_” 前缀。

  • formLogin():启用基于表单的身份验证。

  • loginProcessingUrl(String):定义处理登录请求的 URL。

  • permitAll():允许所有用户(即使未经认证)访问使用 antMatchers 定义的路径。

  • anonymous() 表示可以被未登录的用户(即匿名用户)访问。

  • anyRequest():应用于所有剩余的 URL。

  • authenticated():要求在处理给定的请求之前进行身份验证,即,允许认证过的用户访问。

  • denyAll():无条件拒绝所有访问。

  • csrf():用于配置 CSRF(跨站请求伪造)保护。

  • disable():禁用 csrf 保护或其他配置。

  • exceptionHandling():配置异常处理。

  • accessDeniedHandler(AccessDeniedHandler):自定义处理访问被拒绝的情况的策略。

  • httpBasic():启用 HTTP 基本认证。

  • logout():配置注销功能。

  • logoutUrl(String):设置触发注销操作的 URL。

  • logoutSuccessUrl(String):注销成功后重定向的 URL。

  • and():表示我们已经完成了授权相关的配置,并且需要添加一些其他的 HTTP 配置。

  • not():对其他访问结果取反。

  • cors():配置跨源资源共享(CORS)。

  • headers():配置各种 HTTP 头以增强安全性。

  • rememberMe():启用"记住我"的功能。

  • sessionManagement():配置会话管理。

  • maximumSessions(int):限制同一用户的并发会话数。

  • addFilter(Filter filter):添加过滤器在链中对应的还有 Before 和 After 方法。

除了上述方法,还有一些专门的配置器可以针对不同的模块来配置 HttpSecurity,如 OAuth2, SAML, LDAP 等。

这些 HttpSecurity 方法通常会以链式调用的方式被调用,并最终构成一个安全配置顺序,定义了整个应用的安全策略。这种方法的组合几乎可以支持所有标准的 Web 安全需求。


总结

Spring Security 是一个功能强大且灵活的框架,可帮助开发人员轻松实现应用程序的安全性需求。它提供了丰富的功能和配置选项,可以适应各种安全场景和要求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/244179.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ROS2 学习08 导航Nav2:简介、安装、测试效果、错误处理

1、简介 在ROS2中自动导航使用Nav2来实现。 Nav2 使用几个独立的模块化服务&#xff0c;通过 ROS 2接口&#xff08;例如动作服务器或服务&#xff09;与行为树 (BT) 通信。 Nav2 输入包括&#xff1a;TF转换、一个地图源、一个行为树 (BT) XML 文件和相关的传感器数据源; Nav…

基于javaweb教务管理系统

一、系统架构 前端&#xff1a;jsp | jquery | layui 后端&#xff1a;spring | springmvc | mybatis 环境&#xff1a;jdk1.8 | maven | mysql 二、代码及数据库 三、功能介绍 01. 登录页 02. 主页 03. 系统管理-用户管理 04. 系统管理-角色管理 05. 系统管理-权限管…

《PySpark大数据分析实战》-08.宽窄依赖和阶段划分

&#x1f4cb; 博主简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是wux_labs。&#x1f61c; 热衷于各种主流技术&#xff0c;热爱数据科学、机器学习、云计算、人工智能。 通过了TiDB数据库专员&#xff08;PCTA&#xff09;、TiDB数据库专家&#xff08;PCTP…

express 下搞一个 websocket 长连接

安装模块 npm i express npm i express-ws 新建文件app.js 先安排源码 监听端口 7777 var express require(express) var app express() require(express-ws)(app)var port 7777 var clientObject {} app.ws(/, (client, req) > {// 连接var key req.socket.re…

运筹学经典问题(七):旅行商问题(TSP)

问题描述 给定一系列城市和每对城市之间的距离&#xff0c;求解访问每座城市一次并回到起始城市的最短回路。 数学建模 集合&#xff1a; V V V&#xff1a;城市集合 常量&#xff1a; c i j c_{ij} cij​&#xff1a;城市 i i i到城市 j j j之间距离, i ≠ j i \neq j i…

基于C++的简单BP神经网络(C++)

需求&#xff1a;在某些无网络的实验机器上&#xff0c;由于某些任务需求&#xff0c;需要拟合特定的函数&#xff0c;因此需要部署基于C开发的神经网络&#xff0c;本文在不使用外部库的情况下&#xff0c;编写简单的神经网络&#xff0c;实现简单函数的拟合。 一、简介 本文…

我常用的几个经典Python模块

Python常用的模块非常多&#xff0c;主要分为内置模块和第三方模块两大类&#xff0c;且不同模块应用场景不同又可以分为文本类、数据结构类、数学运算类、文件系统类、爬虫类、网络通讯类等多个类型。 大家常用的内置模块比如&#xff1a;math、re、datetime、urllib、os、ra…

CountDownLatch用法、详解

目录 ​编辑 概述&#xff1a; 应用场景&#xff1a; 优点&#xff1a; 缺点&#xff1a; 主要方法&#xff1a; 1. CountDownLatch(int count)&#xff1a; 2. void await()&#xff1a; 3. boolean await(long timeout, TimeUnit unit)&#xff1a; 4. void countDo…

【Python】计算一年内的总天数(还有跨年日期)

花了一段时间才找到Python中求一年中总日数&#xff08;total day of the Year&#xff09;的格式代码&#xff0c;所以也把计算方法记录下来。 基本 首先&#xff0c;简单地找出一年中的总天数&#xff0c; strftime() 和 strptime() 的格式代码是 %j ↓看这里 使用 strft…

基于当前实时云渲染的特点,用户体验主要受哪些因素影响?

在回答这个问题之前我们首先需要理解什么是实时云渲染&#xff1f; 点量实时云渲染是一种基于云计算低延迟传输&#xff0c;实现各种轻终端便捷使用云端大型软件和3D应用的一种云技术解决方案。这一技术解决方案通过将应用程序或内容置于云端服务器上运行&#xff0c;然后以视…

测试用例设计方法六脉神剑——第四剑:石破天惊,功能图法攻阵

1 引言 前面几篇文章为我们讲述了因果图、判定表、正交试验等几种方法&#xff0c;主要是针对于不同条件输入输出的组合进行测试&#xff0c;但在实际需求中&#xff0c;我们也常会遇到需要对被测对象的状态流转进行验证的情况&#xff0c;此时前面几种方法将不再适用&#xf…

测试用例设计方法:功能图

1 引言 前面几篇文章为我们讲述了因果图、判定表、正交试验等几种方法&#xff0c;主要是针对于不同条件输入输出的组合进行测试&#xff0c;但在实际需求中&#xff0c;我们也常会遇到需要对被测对象的状态流转进行验证的情况&#xff0c;此时前面几种方法将不再适用&#xf…

OpenHarmony 鸿蒙系统之开发环境安装

一、首先在下方链接网址中下载DevEco Studio的安装包。 DevEco Studio历史版本下载-HarmonyOS应用开发官网

Linux CentOS7 Docker安装Jenkins

1 sudo yum update #确保yum包更新到最新 service network restart #重启网络 2、查询镜像 docker search jenkins 3、拉取镜像 docker pull jenkins/jenkins #拉取镜像 4、创建Jenkins工作目录&#xff0c;并将容器内目录挂载到此目录…

23.12.10日总结

周总结 这周三的晚自习&#xff0c;学姐讲了一下git的合作开发&#xff0c;还有懒加载&#xff0c;防抖&#xff0c;节流 答辩的时候问了几个问题&#xff1a; 为什么在js中0.10.2!0.3? 在js中进行属性运算时&#xff0c;会出现0.10.20.300000000000000004js遵循IEEE754标…

CSS伪元素的特殊机制

概念 伪元素是CSS中的一种特殊机制&#xff0c;用于在元素的特定位置插入虚拟的内容。它们不是实际存在于HTML文档中的元素&#xff0c;而是通过CSS样式来创建和控制的。 伪元素使用双冒号&#xff08;::&#xff09;作为标识符&#xff0c;用于区分伪类选择器&#xff08;使…

Linux Shell——基本语法(变量、流程控制)

shell基本语法 一、变量二、流程控制 总结 最近学习了shell脚本&#xff0c;记录一下相关语法 一、变量 变量是很重要的&#xff0c;是用于存储数据值的容器 变量名要遵循以下规则&#xff1a; &#xff08;1&#xff09;只能包含字母、数字和下划线 &#xff08;2&#xff09…

鸿蒙开发组件之Web

一、加载一个url myWebController: WebviewController new webview.WebviewControllerbuild() {Column() {Web({src: https://www.baidu.com,controller: this.myWebController})}.width(100%).height(100%)} 二、注意点 2.1 不能用Previewer预览 Web这个组件不能使用预览…

Android camera的metadata

一、实现 先看一下metadata内部是什么样子&#xff1a; 可以看出&#xff0c;metadata 内部是一块连续的内存空间。 其内存分布大致可概括为&#xff1a; 区域一 &#xff1a;存 camera_metadata_t 结构体定义&#xff0c;占用内存 96 Byte 区域二 &#xff1a;保留区&#x…

Linux install manual 1Panel

前言 1Panel 是一个现代化、开源的 Linux 服务器运维管理面板。1Panel 的功能和优势包括: 快速建站:深度集成 Wordpress 和 Halo,域名绑定、SSL 证书配置等一键搞定;高效管理:通过 Web 端轻松管理 Linux 服务器,包括主机监控、文件管理、数据库管理、容器管理等;安全可…