Spring Security使用詳解11(獲取當前用戶的用戶名、id)

有時我們需要獲取當前登錄的用戶信息(比如用戶名),通常有如下幾種方式來實現。

 

方法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 會將 Username、Password、Authentication、Token 注入到 Principal 接口中,我們可以直接獲取使用:

@RestController
public class HelloController {
 
    @GetMapping("/hello")
    public String hello(Principal principal) {
        // 注意:如果未登錄,principal 爲 null
        return "當前登錄用戶:" + principal.getName();
    }
}

 

附:獲取登錄用戶的 id 等其他信息

(1)如果我們是基於數據庫的用戶角色配置的話,那麼會創建用戶表對應的實體類,同時用戶實體類需要實現 UserDetails 接口。

關於基於數據庫的用戶角色配置認證更詳細的用法,可以參考我之前顯得文章:

Spring Security使用詳解3(基於數據庫的用戶角色配置)

@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)運行結果如下:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章