Spring Security5+ 用户认证、授权及注销

目录

前言

一、Spring Security 的简单介绍

二、用户认证与授权

1、导入相关依赖

2、授权(Authorization)

3、认证 (Authentication)

三、用户注销


前言

Spring Security是一个专注于为Java应用程序提供身份验证和授权的框架。与所有Spring项目一样,Spring Security的真正强大之处在于它可以很容易地扩展以满足定制需求。虽然拦截器、过滤器也可以在一定程度上起到安全认证的作用,但是对码农来说,大量原生的代码及代码冗余,十分的不友好。本文以Spring Security5.6.2版本来对用户认证、授权、注销做个说明。

一、Spring Security的简单介绍

1、到博主写博客的时间为止,Spring Security已经更新到了5.6.2了,作为Spring全家桶之一,其可谓是出身名门,当然新版本增加了一些功能,但也可能会出现版本不兼容的问题。

2、功能

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

2) 防止攻击,如会话固定,点击劫持,跨站请求伪造等

3) 集成了Servlet API

4) 与Spring Web MVC的可选集成

5) 还定制了一些功能,比如增加了一些加密算法

二、用户认证与授权

1、导入相关依赖

<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>
        </dependency>

注:导入spring-security依赖后,系统会自动过滤,没有进行登录的话,会自动跳转到Spring Security定制的login界面上 。通过查看源码HttpSecurity.java ,不难发现系统默认自动生成一个登录页面在URL里显示“/login”,认证失败会重定向到“/login?error”,并且登录页面的详细信息可以在formloginconfiguration .loginpage (String)中找到。

 

那它定制的登录界面,咱咋知道它的登录名和密码呢?你在源码里可以发现大量的hasRole("USER"),登录名就是它了,甚至还可以小写。那密码呢?运行程序后控制台会自动生成一个秘钥,当然人家会提示你:此生成的密码仅供开发使用。在生产环境中运行应用程序之前,必须更新安全配置。

2、授权(Authorization)

学过网络工程的人,可能会对AAA认证机制有所了解,Cisco开发的一个提供网络安全的系统,包括身份验证(Authentication)、授权 (Authorization)和统计 (Accounting)。那Spring Security的授权怎么配置呢?

1)写一个安全配置类:SecurityConfig,让这个类继承WebSecurityConfigurerAdapter,然后重写configure(HttpSecurity http)方法

 2)授权与拦截验证

一般而言,首页所有人都能访问,功能页只有对应有权限的人才可以访问。那如何定制授权的规则,拦截非授权的请求呢?阅读源码可知,可以通过HttpSecurity的参数名http调用授权请求,并且授权调用方法的形式类似链式编程。

antMatcher用在多个HttpSecurity的场景下,用来为每个HttpSecurity过滤。没有权限会调用formLogin()方法,回到登录界面 。比如:我在项目里允许访问项目主路径"/"的请求,其它请求都要经过拦截验证,让不同的vip跳到它们的专属页面。

 SecurityConfig授权配置如下:

//授权
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //首页所有人能访问,功能页只有对应有权限的人才可以访问
        //请求授权的规则
        http.authorizeHttpRequests().antMatchers("/").permitAll()
                //允许访问项目主路径"/"的请求,其它请求都要经过拦截验证
                .antMatchers("/level1/**").hasRole("vip1")
                .antMatchers("/level2/**").hasRole("vip2")
                .antMatchers("/level3/**").hasRole("vip3");
        //没有权限默认到登录页面,需要开启登录的页面
        http.formLogin();

    }

3)结果

配置完成后,系统不会自动跳转到Spring Security定制的login界面上,而是到自己写的主页面index.html上。当然点击不同vip的专属资源,需要进行登录认证。

3、认证 (Authentication)

1)认证重写了configure(AuthenticationManagerBuilder auth)方法,数据正常应该从数据库里面读(auth.jdbcAuthentication()),为了方便,本文是从内存里直接读的(auth.inMemoryAuthentication())从内存读取当然也更快一点了。

2)进行认证配置

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //这些数据正常应该从数据库里面读(auth.jdbcAuthentication()),下面是从内存里读的(auth.inMemoryAuthentication())
        auth.inMemoryAuthentication()
                .withUser("guest")
                .password("{noop}123456")
                .roles("vip1")
                .and().withUser("user")//and()拼接
                .password("{noop}55555")
                .roles("vip1","vip2")
                .and().withUser("admin")
                .password("{noop}root").roles("vip1","vip2","vip3");
    }

在这里,我们创建了三类用户:

第一类:游客(guest) ,拥有一个查看权限(这里定义为vip1)

第二类:登录用户(user),拥有查看和操作的权限(这里定义为vip1和vip2)

第三类:管理员(admin),拥有查看、操作和管理的权限(这里定义为vip1、vip2和vip3)

使用.and()进行多用户拼接

3)Spring Security5.0+加密方法说明

当进行如下配置时,会出现500错误,并且出现:There is no PasswordEncoder mapped for the id "null",这是由于新版本中一定要指定密码编码(PasswordEncoder)的方式。

 在Spring Security5.0+中 新增了很多的加密方法。spring security 5支持的加密 方式有bcrypt、ldap、MD4、MD5、noop、pbkdf2、scrypt、SHA-1、SHA-256、 sha256。

为方便校验测试,{noop}是制定密码加密策略为不加密 。noop的意思是明文保存的密码 (noop: No Operation)。此PasswordEncoder仅用于遗留和测试目的,不被认为是安全的。一个什么都不做的密码编码器,对于使用纯文本密码的测试非常有用。

spring security官方推荐使用更加安全的bcrypt加密方式。该加密方式使用了BCrypt强哈希函数的PasswordEncoder的实现,并且强度参数越大,需要以指数方式对密码进行哈希处理的工作量就越大。

 改善之后的代码如下:

 @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //这些数据正常应该从数据库里面读(auth.jdbcAuthentication()),下面是从内存里读的(auth.inMemoryAuthentication())
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("guest")
                .password(new BCryptPasswordEncoder().encode("123456"))
                .roles("vip1")
                .and().withUser("user")//and()拼接
                .password(new BCryptPasswordEncoder().encode("55555"))
                .roles("vip1","vip2")
                .and().withUser("admin")
                .password(new BCryptPasswordEncoder().encode("root")).roles("vip1","vip2","vip3");

    }

4)结果测试

编写一个Controller类

package com.study.controller;


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
public class RouterController {
    @RequestMapping({"/", "/index"})
    public String index() {
        return "index";
    }

    @RequestMapping("/toLogin")
    public String toLogin() {
        return "views/login";
    }

    @RequestMapping("/level1/{id}")
    public String level1(@PathVariable("id") int id) {
        return "views/level1/" + id;
    }

    @RequestMapping("/level2/{id}")
    public String level2(@PathVariable("id") int id) {
        return "views/level2/" + id;
    }

    @RequestMapping("/level3/{id}")
    public String level3(@PathVariable("id") int id) {
        return "views/level3/" + id;
    }
}

 结果如下:管理员用户可以访问到vip3下的资源

三、用户注销

1、首先,应该开启注销功能,注销完成之后让它跳转至首页

http.logout().logoutSuccessUrl("/");

2、通过源码注释,可知:HttpSecurity提供注销的支持,在使用WebSecurityConfigurerAdapter时会自动应用。默认情况下,会访问URL“/logout”地址,并使HTTP会话无效、清除配置的任何rememberMe()身份验证、清除SecurityContextHolder,然后重定向到“/login?success”来注销用户。 

3、结果 

注销之后,成功退到首页 

<think>好的,我需要处理用户关于Spring Security与JWT实现权限认证的面试题请求。首先,用户提到了三个引用内容,我需要仔细阅读这些引用,确保答案中的信息能够正确引用这些来源。 根据引用[1],里面提到了RBAC的权限配置、Spring Security的基本使用,以及结合JWT实现前后端分离,包括JSON登录和密码加密。引用[2]和[3]则涉及具体的配置类,如继承WebSecurityConfigurerAdapter,以及JWT的加密方式和刷新令牌机制。特别是引用[3]提到了refreshToken解决令牌续期问题,还有加密方式的问题。 接下来,我需要生成相关的面试题。用户可能希望涵盖基础概念、配置步骤、核心组件、常见问题及解决方案等方面。需要确保问题覆盖Spring Security与JWT的整合流程、安全配置、权限管理、令牌刷新机制、加密方法等关键点。 然后,考虑问题的结构。通常面试题会分为基础概念、配置与整合、权限控制、安全机制、优化与扩展等部分。每个部分下需要设计具体的问题,确保问题有层次,从浅入深。 例如,基础概念部分可以问JWT的结构和优势,Spring Security的作用。配置与整合部分涉及如何配置Spring Security与JWT,核心配置类是什么。权限控制会涉及RBAC模型和注解的使用。安全机制可能包括密码加密、CSRF保护、令牌刷新。优化部分可能涉及性能优化和分布式系统的处理。 同时,要确保答案中的引用正确,比如提到令牌刷新机制时要引用[3],密码加密引用[1],配置类引用[2]。还要注意使用中文回答,行内公式用$...$,独立公式用$$...$$,但在这个问题中可能公式较少,但需要检查是否有数学表达式的情况。 最后,生成相关问题时要覆盖用户可能关心的各个方面,帮助用户全面准备面试。需要确保问题数量适中,涵盖主要知识点,并且问题之间有逻辑连贯性。</think>### Spring Security与JWT实现权限认证面试题解析 #### 1. **基础概念** **Q1: JWT的结构是什么?它在认证中有什么优势?** A1: JWT由三部分组成:头部(Header)、载荷(Payload)、签名(Signature),格式为`Header.Payload.Signature`。优势包括: - **无状态**:服务端无需存储会话信息[^3]; - **跨域支持**:适合前后端分离架构[^1]; - **自包含性**:载荷可存储用户基本信息(如角色、权限)。 **Q2: Spring Security的核心功能是什么?** A2: Spring Security提供身份验证(Authentication)和授权(Authorization)功能,支持RBAC(基于角色的访问控制)模型[^1],可拦截请求并验证用户权限。 --- #### 2. **配置与整合** **Q3: 如何配置Spring Security与JWT整合?** A3: 关键步骤包括: 1. **继承`WebSecurityConfigurerAdapter`**:覆盖`configure`方法,定义安全规则和过滤器链[^2]。 2. **自定义`JwtAuthenticationFilter`**:拦截请求并解析JWT令牌。 3. **配置密码加密**:使用`BCryptPasswordEncoder`[^1]。 4. **禁用Session**:通过`sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)`实现无状态。 **Q4: Spring Security中`UserDetailsService`的作用是什么?** A4: 该接口用于加载用户信息(如用户名、密码、权限),需实现`loadUserByUsername`方法,从数据库或其他存储中查询用户数据[^1]。 --- #### 3. **权限控制** **Q5: 如何实现基于RBAC的权限控制?** A5: - **角色表设计**:用户表、角色表、权限表通过中间表关联[^1]。 - **注解控制**:使用`@PreAuthorize("hasRole('ADMIN')")`在方法或接口上声明权限。 - **动态配置**:通过`HttpSecurity`的`antMatchers()`配置URL路径权限[^2]。 **Q6: 如何实现接口级别的权限校验?** A6: 结合`@PreAuthorize`注解和SpEL表达式,例如: ```java @PostMapping("/admin") @PreAuthorize("hasAuthority('ADMIN_WRITE')") public void adminOperation() { ... } ``` --- #### 4. **安全机制与优化** **Q7: JWT如何解决令牌过期问题?** A7: 使用**刷新令牌(Refresh Token)**机制: - 当JWT即将过期时,客户端用Refresh Token请求新JWT。 - Refresh Token有效期较长,但需存储于服务端或加密签名。 **Q8: JWT的签名算法有哪些?如何防止令牌篡改?** A8: 常用算法包括HMAC(如HS256)和RSA(如RS256)。签名通过密钥生成,验证时重新计算签名以检测篡改。 **Q9: 如何防御CSRF攻击?** A9: Spring Security默认启用CSRF保护,但若使用JWT的无状态架构,需显式禁用: ```java @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); } ``` --- #### 5. **常见问题与扩展** **Q10: 分布式系统中JWT如何实现注销?** A10: 传统JWT无法直接注销,可通过以下方案: - **短期令牌**:缩短JWT有效期,依赖Refresh Token续期。 - **黑名单**:服务端维护失效令牌列表,但需额外存储。 **Q11: Spring Security如何整合OAuth2?** A11: 使用`spring-security-oauth2`库,配置授权服务器(`AuthorizationServerConfigurer`)和资源服务器(`ResourceServerConfigurer`),支持OAuth2协议与JWT结合。 --- ###
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值