SpringBoot整合SpringSecurity [超详细] (二)获取用户信息


前言

前置条件:

  • 要求掌握简单的项目搭建
  • (默认用户名和随机密码)或者(自定义用户名和密码)

项目结构如下:

在这里插入图片描述

一、代码版

在这里插入图片描述

package cn.cy.controller;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class HelloController {
    // 此处的 User是SpringSecurity提供的一个封装用户的类
    @RequestMapping("/getUser")
    public User getUser(){
        // SecurityContext 安全上下文. 用来存储认证授权的相关信息(账号信息和相关权限)
        SecurityContext context = SecurityContextHolder.getContext();
        // Authentication 封装了登录用户信息的对象
        Authentication authentication = context.getAuthentication();
        // 基于认证对象获取用户身份信息
        User user = (User)authentication.getPrincipal();
        System.out.println(user);
        return user;
    }
}

请添加图片描述

二、注解版

在这里插入图片描述

package cn.cy.controller;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
public class HelloController {
    // 此处的 User是SpringSecurity提供的一个封装用户的类
    @RequestMapping("/getUser")
    public UserDetails getUser(@AuthenticationPrincipal UserDetails user){
        System.out.println(user);
        return user;
    }
}

请添加图片描述

三、拓展

1. SecurityContext接口

安全上下文,这个接口可以设置(setter)或者获取(getter)当前的认证对象。

SecurityContext源码:

public interface SecurityContext extends Serializable {
	/**
	 * 获取当前经过身份验证的主体,或身份验证请求令牌。
	 * @return 如果没有可用的身份验证信息,则 Authentication 或 null
	 */
    Authentication getAuthentication();
	/**
	 * 更改当前经过身份验证的主体,或删除身份验证信息。
	 * @param authentication – 新的身份验证令牌,如果不应存储进一步的身份验证信息,则为 null
	 */
    void setAuthentication(Authentication authentication);
}

2. Authentication接口

认证对象

  • principa
    • 定义认证的用户,通常指的就是UserDetail对象
  • credentials
    • 登录凭证,一般指的是密码,当用户登录成功之后,这个密码是不被保存的,以防止泄露 – Password=[PROTECTED]
  • authorities
    • 用户的权限信息

Authentication源码

public interface Authentication extends Principal, Serializable {

	/**
	 * 获取用户权限
	 */
	Collection<? extends GrantedAuthority> getAuthorities();
	
	/**
	 * 用来获取用户凭证,一般来说就是密码。
	 */
	Object getCredentials();

	/**
	 * 用来获取用户的详细信息,可能是当前的请求之类。
	 */
	Object getDetails();

	/**
	 * 用来获取当前用户信息信息,可能是一个用户名,也可能是一个用户对象。
	 */
	Object getPrincipal();

	/**
	 * 当前用户是否认证成功。
	 */
	boolean isAuthenticated();
	
	/**
	 * 
	 */
	void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;

}

通过上述的信息,可以看出在SpringSecurity中,只要我们获取了Authentication对象,就可以获取到登录用户的用户详情了。

3. SecurityContextHolder

工具类,用于存放 SecurityContext ,默认是使用ThreadLocal实现的,这样就保证了本线程内所有的方法都可以获得SecurityContext对象

3.1 SecurityContextHolder重要方法
  • public static SecurityContext getContext()
    • 获取SercurityContext安全上下文对象
  • public static void setContext(SecurityContext context)
    • 设置/修改SercurityContext安全上下文对象
  • public static void clearContext()
    • 清除SercurityContext安全上下文对象
  • public static SecurityContext createEmptyContext()
    • 创建一个空的SercurityContext安全上下文对象
3.2 SecurityContextHolder存储策略
public class SecurityContextHolder {

	public static final String MODE_THREADLOCAL = "MODE_THREADLOCAL";

	public static final String MODE_INHERITABLETHREADLOCAL = "MODE_INHERITABLETHREADLOCAL";

	public static final String MODE_GLOBAL = "MODE_GLOBAL";
}
  1. MODE_THREADLOCAL

    • 将SecurityContext存放在ThreadLocal中,ThreadLocal的特点是在哪个线程中存储就要在哪个线程中读取,这其实非常适合web应用,因为在默认情况下,一个请求无论经过多少Filter到达Servlet,都是由一个线程来处理的,这也是SecurityContextHolder默认的存储策略,这种存储策略意味着如果在具体的业务代码中,开启了子线程,在子线程去获取登录用户数据,就会获取不到。
  2. MODE_INHERITABLETHREADLOCAL

    • 这种存储模式适用于多线程环境,如果希望在子线程中也能够获取到登录用户数据,那么可以使用这种存储模式。
  3. MODE_GLOBAL

    • 这种存储模式实际上是将数据保存在一个静态变量中,在JAVAWeb开发中,这种模式很少使用到

4. SecurityContextHolder,SecurityContext,Authentication的关系

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,我会尽量详细地讲解使用 Spring Security 和 Redis 实现用户登录和权限控制的细节。 首先,你需要在你的项目中引入 Spring Security 和 Redis 的依赖。 在配置文件中,你需要配置 Redis 的连接信息,并且指定使用 Redis 作为 Spring Security 的缓存。 然后,你需要定义一个 UserDetailsService,它负责从数据库中读取用户的登录信息。在这个类中,你可以使用 RedisTemplate 将用户信息缓存到 Redis 中。 接着,你需要配置 Spring Security 的认证流程。这包括指定使用哪种认证方式(比如表单认证),以及如何处理登录请求和登录成功/失败的情况。 最后,你还需要配置权限控制。这包括指定哪些路径需要身份认证和授权,以及如何检查用户是否具有访问某个路径的权限。 在这些配置完成之后,当用户尝试访问受保护的路径时,Spring Security 会自动拦截请求并进行身份认证和权限检查。如果用户身份认证成功且具有访问该路径的权限,就会放行请求;否则, ### 回答2: 使用Spring Security和Redis实现用户登录以及权限控制主要涉及以下几个方面的细节: 1. 用户认证:用户输入用户名和密码后,Spring Security会将其传递给一个认证管理器(AuthenticationManager),该管理器会根据用户提供的信息进行认证。在认证过程中,可以使用Redis作为缓存存储用户信息,提高认证的效率。 2. 密码加密:为了增强安全性,用户的密码通常应该经过加密处理后才进行存储。Spring Security提供了多种加密方式,如BCrypt、SHA等,可以根据项目需求选择适合的加密方式。在存储用户密码时,可以使用Redis的存储功能进行持久化存储。 3. 授权管理:一旦用户通过认证,Spring Security会为该用户分配相应的权限。可以将用户的权限信息存储在Redis中,方便后续的权限控制操作。通过配置合适的访问规则,可以根据用户的角色或权限对不同的资源进行访问控制。 4. Session管理:在用户登录后,系统会为用户生成一个会话(Session),用于记录用户的登录状态。可以将会话信息存储在Redis中,由Spring Security进行管理。通过Redis的分布式存储特性,可以实现多个应用服务器之间的会话共享,增强系统的可扩展性和容错性。 使用Spring Security和Redis实现用户登录以及权限控制的细节可以通过使用Spring Security提供的相关注解和配置来完成。这些注解和配置包括用户认证的自定义逻辑、密码加密配置、权限配置、会话管理配置等。同时,为了实现与Redis的集成,可以使用Spring Data Redis提供的工具类和注解,简化与Redis的交互操作。通过合理的配置和编码实现,可以保障系统的安全性和可扩展性。 ### 回答3: 使用Spring Security和Redis实现用户登录和权限控制的过程可以分为以下几个细节。 首先,我们需要在Spring Boot项目中配置Spring Security和Redis的相关依赖。在pom.xml文件中添加相应的依赖,并进行配置。 接下来,我们需要创建一个用户模型,包含字段如用户名、密码和权限等。可以使用Spring Data JPA来管理用户模型的持久化和CRUD操作。 在用户登录过程中,首先用户需要提供用户名和密码。Spring Security可以提供默认的登录表单页面,也可以自定义登录页面。用户提交登录请求后,Spring Security会拦截该请求,并通过验证用户名和密码的方式,验证用户身份的合法性。这可以通过自定义UserDetailsService来实现,UserDetailsService可以从数据库(MySQL等)中获取用户信息,用于验证用户身份。当验证成功后,Spring Security会生成一个Token,并将其存储到Redis中。 在权限控制方面,用户在登录后,可以通过访问需要权限的接口或资源。Spring Security可以通过对应的注解,如@PreAuthorize、@PostAuthorize等,在方法级别或类级别上添加权限控制规则。这些注解可以用来定义访问某个接口或资源需要的权限。当用户访问某个需要权限的接口时,Spring Security会通过Token从Redis中获取用户信息,并根据用户的权限与接口所需权限进行对比。如果用户拥有足够的权限,就可以访问接口;否则,将会返回403错误。 另外,在权限控制方面,可以利用Spring Security提供的@PreAuthorize注解进行动态权限控制,即根据用户当前的权限动态决定用户是否可以访问某个接口。这可以通过在注解中添加SpEL表达式来实现,例如:@PreAuthorize("hasAnyAuthority('admin','user')"),表示只有拥有admin或user权限的用户才能够访问该接口。 综上所述,使用Spring Security和Redis实现用户登录和权限控制,通过验证用户身份和对用户权限进行控制,可以保障系统的安全性和权限管理。该方案具备灵活性,并且可以与其他框架和工具(如Spring Cloud等)结合使用,实现更加完整的分布式系统的用户登录和权限控制功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值