返回 导航

SpringBoot / Cloud

hangge.com

SpringBoot - 安全管理框架Spring Security使用详解11(获取当前用户的用户名、id)

作者:hangge | 2020-01-10 08:02
    有时我们需要获取当前登录的用户信息(比如用户名),通常有如下几种方式来实现。

方法1:通过 Authentication.getPrincipal() 获取用户信息

(1)通过 Authentication.getPrincipal() 可以获取到代表当前用户的信息,这个对象通常是 UserDetails 的实例。通过 UserDetails 的实例我们可以获取到当前用户的用户名、密码、角色等信息。
    Spring Security 使用一个 Authentication 对象来描述当前用户的相关信息,而 SecurityContext 持有的是代表当前用户相关信息的 Authentication 的引用。
    这个 Authentication 对象不需要我们自己去创建,在与系统交互的过程中,Spring Security 会自动为我们创建相应的 Authentication 对象,然后赋值给当前的 SecurityContext
@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

        if (principal instanceof UserDetails) {
            return ((UserDetails) principal).get.getUsername();
        }

        if (principal instanceof Principal) {
            return ((Principal) principal).getName();
        }

        return "当前登录用户:" + String.valueOf(principal);
    }
}

(2)由于获取当前用户的用户名是一种比较常见的需求,其实 Spring Security Authentication 中的实现类中已经为我们做了相关实现,所以获取当前用户的用户名有如下更简单的方式:
@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        return "当前登录用户:" + SecurityContextHolder.getContext().getAuthentication().getName();
    }
}

方法2:通过注入 Principal 接口获取用户信息

    在运行过程中,Spring 会将 UsernamePasswordAuthenticationToken 注入到 Principal 接口中,我们可以直接获取使用:
@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello(Principal principal) {
        // 注意:如果未登录,principal 为 null
        return "当前登录用户:" + principal.getName();
    }
}

附:获取登录用户的 id 等其他信息

(1)如果我们是基于数据库的用户角色配置的话,那么会创建用户表对应的实体类,同时用户实体类需要实现 UserDetails 接口。
关于基于数据库的用户角色配置认证更详细的用法,可以参考我之前显得文章:
@NoArgsConstructor
@ToString
public class User implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    private Boolean enabled;
    private Boolean locked;
    private List<Role> roles;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (Role role : roles) {
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }
        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 !locked;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }

    /** get、set 方法 **/

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
    }

    public Boolean getLocked() {
        return locked;
    }

    public void setLocked(Boolean locked) {
        this.locked = locked;
    }

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }
}

(2)我们同样通过 Authentication.getPrincipal() 可以获取当前登录用户的 UserDetails 实例,然后再转换成自定义的用户实体类 User,这样便能获取用户的 ID 等信息:
@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello() {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = (User)principal;
        return "当前登录用户信息:" + user.toString();
    }
}

(3)运行结果如下:

评论

全部评论(0)

回到顶部