初识SpringSecurity

发布时间:2023年12月17日

目录

前言

特点

快速开始

导入依赖

运行项目

访问服务

权限控制

实现UserDetails接口

添加SecurityConfig配置类

测试接口DemoController

设置权限控制authorizeHttpRequests

结果分析

总结


前言

Spring Security是一个强大且高度可定制的身份验证和访问控制框架。它是保护基于Spring的应用程序的事实标准。


Spring Security是一个专注于为Java应用程序提供身份验证和授权的框架。与所有Spring项目一样,Spring Security的真正力量在于它可以多么容易地扩展以满足自定义需求。

特点

  • 对身份验证和授权的全面且可扩展的支持

  • 防止会话固定、点击劫持、跨站点请求伪造等攻击

  • Servlet API集成

  • 与Spring Web MVC的可选集成

快速开始

导入依赖

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

运行项目

查看控制台的输出,会发现出现了警告。

警告翻译:

使用生成的安全密码:e3e4d1a9-2520-49a8-bb0b-359c2ed19314
此生成的密码仅供开发使用。在生产环境中运行应用程序之前,必须更新您的安全配置。?

因为我们只是引入了SpringSecurity的依赖,并没有对其进行配置。所以此时使用的都是默认的配置,这些配置都是可以自定义的。

访问服务

访问后会跳转到登录页面,默认用户名user,密码在控制台中查看。默认的登录请求为/login,只有登录成功后才能继续访问。

输入用户名和密码,会跳转页面。但是我们没有设置登录成功后的页面跳转,所以结果是404?Not Found。其实我们没有必要去设置这个跳转页面,因为开发都是基于前后端分离的模式。前端发起登录请求,我们后端响应结果就行了。也就意味着这个登录页面也是多余的,后面我们会将这个登录禁用。

到这里就是对SpringSecurity的快速开始,接下来我们来看对权限的控制。

权限控制

实现UserDetails接口

SpringSecurity需要通过实现了UserDetails接口的类来判断用户登录和权限控制,我们要做的就是查询用户信息,然后封装成UserDetails对象并交给Security进行处理。

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;

public class SysUser implements UserDetails {

    private final String username;
    private final String password;
    private final Collection<? extends GrantedAuthority> authorities;

    public SysUser(String username, String password, Collection<? extends GrantedAuthority> authorities) {
        this.username = username;
        this.password = password;
        this.authorities = authorities;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        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 true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        // 是否凭据未过期
        return true;
    }

    @Override
    public boolean isEnabled() {
        // 是否账号可用
        return true;
    }
}

添加SecurityConfig配置类

密码编码器:必须指定密码编码器,因为密码不允许明文存储。账号的密码为123abc,但存储的密码可不是123abc,而是经过编码后生成的一串字符串。

添加用户到内存:这里就直接添加用户到内存,正常是要保存在数据库里。道理其实是一样的,都是要提供给Security封装实现了UserDetails接口的类。

配置过滤器链:这个是很重要的配置,Security的扩展性很强,就是因为可以在这里配置各种自定义的设置。例如,我们可以配置自定义身份验证过滤器,从而替换默认的配置。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    // 添加用户到内存
    @Bean
    public InMemoryUserDetailsManager inMemoryUserDetailsManager() {

        String password = "123abc";
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String encode = bCryptPasswordEncoder.encode(password);

        SysUser sysUser = new SysUser("艾伦", encode,
                AuthorityUtils.commaSeparatedStringToAuthorityList("权限1,权限2"));
        return new InMemoryUserDetailsManager(sysUser);
    }

    // 密码编码器
    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    // 配置过滤器链
    @Bean
    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity httpSecurity) throws Exception {

        // 关闭跨域漏洞防御
        httpSecurity.csrf(AbstractHttpConfigurer::disable);

        return httpSecurity.build();
    }
}

测试接口DemoController

我们编写两个接口,用来测试权限控制。

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

@RestController
public class DemoController {

    @GetMapping("/test1")
    public String demo1() {
        System.out.println("test1访问成功!");
        return "test1访问成功!";
    }

    @GetMapping("/test2")
    public String demo2() {
        System.out.println("test2访问成功!");
        return "test2访问成功!";
    }
}

设置权限控制authorizeHttpRequests

我们的用户只有权限1和权限2,并没有权限3。也就意味着demo1接口我们能正常访问,而demo2接口会因为没有权限访问失败。

注意:这里要指定登录请求为/login,否则会被拒绝访问。

// 配置过滤器链
@Bean
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity httpSecurity) throws Exception {
    httpSecurity.authorizeHttpRequests(authorizeHttpRequests -> authorizeHttpRequests
            .requestMatchers(HttpMethod.GET, "/test1").hasAnyAuthority("权限1", "权限2")
            .requestMatchers(HttpMethod.GET, "/test2").hasAuthority("权限3")
    );

    httpSecurity.formLogin(formLogin -> formLogin
            .loginProcessingUrl("/login") // 登录请求
    );

    // 关闭跨域漏洞防御
    httpSecurity.csrf(AbstractHttpConfigurer::disable);

    return httpSecurity.build();
}

结果分析

结果就是/test1访问成功,而/test2因为没有权限访问失败。

/test1

/test2?

总结

这就是对SpringSecurity的初识,先做一个了解。要想在项目中整合SpringSecurity的话,还需要进一步学习,了解更深层的原理。?

《整合SpringSecurity》

https://blog.csdn.net/qq_74312711/article/details/134992609?spm=1001.2014.3001.5502

文章来源:https://blog.csdn.net/qq_74312711/article/details/134978245
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。