Spring Security

一、基本的概念

1.1 认证、授权、会话

认证(Authentication)

认证是验证用户身份的过程。这通常涉及用户名和密码的验证,但也可以包括其他形式的凭据,如数字证书、生物识别等。

在Java中,你可以通过实现**Authentication**接口或使用现有的安全框架(如Spring Security)来处理认证。在Spring Security中,你可以配置安全策略,包括哪些URL需要认证、如何验证用户凭据等。

授权(Authorization)

授权是确定已认证用户是否有权访问特定资源的过程。这可以基于用户的角色、权限或其他属性。

在Java中,你可以使用基于角色的访问控制(RBAC)或基于声明的访问控制(ABAC)来实现授权。Spring Security提供了强大的授权功能,允许你定义访问控制列表(ACL)或使用注解(如**@PreAuthorize** 、**@PostAuthorize**等)来保护方法或URL。

会话(Session)

会话是用户与应用程序之间的一系列交互。在Web应用程序中,会话通常通过HTTP会话(由服务器管理)或JWT(JSON Web Tokens)等令牌来维护。

在Java的Servlet API中,HttpSession 对象用于管理用户的会话。你可以将会话数据存储在**HttpSession**对象中,并在用户的多个请求之间共享这些数据。然而,请注意,HTTP会话在分布式环境中可能难以管理,因为会话数据通常存储在单个服务器的内存中。

为了解决这个问题,你可以使用基于令牌的会话管理(如JWT)。JWT是一种自包含的令牌,可以在客户端和服务器之间安全地传输用户信息。你可以将JWT作为HTTP请求头的一部分发送,并在服务器端验证它来确定用户的身份和权限。

1.2 RBAC

RBAC(Role-Based Access Control,基于角色的访问控制)是一种广泛使用的访问控制机制,它通过分配角色给用户来管理对资源的访问。在RBAC中,权限不是直接授予用户,而是授予角色,用户通过成为适当角色的成员来获得相应的权限。这种方法简化了权限管理,因为权限的变更只需要在角色级别进行,而不是针对每个用户。

(1)根据角色授权

(2)根据权限授权(推荐)

二、Session

2.1 Session认证的流程通常步骤:

  1. 用户请求登录:用户携带其用户名和密码向服务器发送登录请求。
  2. 服务器验证凭据:服务器收到登录请求后,会验证用户提供的用户名和密码是否正确。
  3. 生成Session:如果用户名和密码验证成功,服务器会生成一个Session对象,该对象包含用户的信息和状态。这个Session对象会保存在服务器端。
  4. 发送Session ID:服务器会生成一个唯一的Session ID,并将其存储在客户端的Cookie中,或者通过其他方式(如URL重写)发送给客户端。客户端在后续的请求中会携带这个Session ID。
  5. 验证Session:当客户端发送新的请求时,会携带之前存储的Session ID。服务器会根据这个Session ID查找对应的Session对象,以验证用户是否已登录以及用户的身份和状态。
  6. 处理请求:如果Session验证成功,服务器会处理客户端的请求,并根据用户的权限和状态返回相应的响应。
  7. Session过期或销毁:如果用户在一段时间内没有活动,或者用户主动退出系统,服务器会销毁相应的Session对象,并清除客户端的Session ID。这样,下次客户端再发送请求时,就无法通过Session验证,需要重新登录。

三、Spring Security

3.1引入依赖

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

3.2在启动类上加上@EnableWebSecurity

@SpringBootApplication
@EnableWebSecurity
public class SpringSecurityApplication {

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

}

3.3这时候发起请求会跳转登录界面(显示效果如下所示)

默认账号: user

密码会在控制台打印出来:

3.4自定义登录账号和密码(admin)

配置类:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    // 默认URL路径跳转到/login, 此url为spring security所提供
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("redirect:/login");
        // 当用户访问根路径时,将会被重定向到登录页面
    }

    @Bean
    public PasswordEncoder getPasswordEncoder(){
        // 这里返回一个PasswordEncoder实例,用于密码编码。
        // 在实际应用中,应该使用BCryptPasswordEncoder来对密码进行加密。
        // return new BCryptPasswordEncoder(10);
        
        // 下面这行代码是用于测试的,它不对密码进行加密,这在生产环境中是不安全的。
        return NoOpPasswordEncoder.getInstance();
    }

    @Bean
    public UserDetailsService userDetailsService(){
        // 创建一个InMemoryUserDetailsManager实例,用于在内存中存储用户信息。
        InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager(
                // 定义三个用户,分别是admin、manager和worker,并设置他们的密码和权限。
                User.withUsername("admin").password(getPasswordEncoder().encode("admin")).authorities("mobile", "salary").build(),
                User.withUsername("manager").password(getPasswordEncoder().encode("manager")).authorities("salary").build(),
                User.withUsername("worker").password(getPasswordEncoder().encode("worker")).authorities("worker").build()
        );
        return userDetailsManager;
    }


}

3.5 登录成功后的跳转的页面 (main.html)

// 启用Spring Security的Web安全功能
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 配置HTTP安全
        http
            // 禁用CSRF保护,这在API服务中通常是有必要的,但在Web应用程序中应谨慎处理
            .csrf().disable()
            // 定义授权请求
            .authorizeRequests()
            // 任何以/mobile/开头的请求都需要用户拥有"mobile"权限
            .antMatchers("/mobile/**").hasAuthority("mobile")
            // 任何以/salary/开头的请求都需要用户拥有"salary"权限
            .antMatchers("/salary/**").hasAuthority("salary")
            // 任何以/common/开头的请求都允许所有用户访问,无需认证
            .antMatchers("/common/**").permitAll()
            // 其他所有请求都需要用户进行认证
            .anyRequest().authenticated()
            .and()
            // 配置表单登录
            .formLogin()
            // 登录成功后默认跳转到/main.html
            .defaultSuccessUrl("/main.html")
            // 登录失败后跳转到/common/loginFailer
            .failureUrl("/common/loginFailer");
    }
}
相关推荐
苹果醋332 分钟前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
Hello.Reader1 小时前
深入解析 Apache APISIX
java·apache
盛派网络小助手1 小时前
微信 SDK 更新 Sample,NCF 文档和模板更新,更多更新日志,欢迎解锁
开发语言·人工智能·后端·架构·c#
菠萝蚊鸭1 小时前
Dhatim FastExcel 读写 Excel 文件
java·excel·fastexcel
旭东怪1 小时前
EasyPoi 使用$fe:模板语法生成Word动态行
java·前端·word
007php0071 小时前
Go语言zero项目部署后启动失败问题分析与解决
java·服务器·网络·python·golang·php·ai编程
∝请叫*我简单先生1 小时前
java如何使用poi-tl在word模板里渲染多张图片
java·后端·poi-tl
ssr——ssss2 小时前
SSM-期末项目 - 基于SSM的宠物信息管理系统
java·ssm
一棵星2 小时前
Java模拟Mqtt客户端连接Mqtt Broker
java·开发语言
鲤籽鲲2 小时前
C# Random 随机数 全面解析
android·java·c#