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

导读:本篇文章讲解 SpringBoot整合SpringSecurity [超详细] (二)获取用户信息,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com


前言

前置条件:

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

项目结构如下:

在这里插入图片描述

一、代码版

在这里插入图片描述

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的关系

在这里插入图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/107635.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!