如何在 Spring Security 中获取 userInformation?

Posted

技术标签:

【中文标题】如何在 Spring Security 中获取 userInformation?【英文标题】:How can I get userInformation in spring security? 【发布时间】:2018-12-16 09:33:40 【问题描述】:

假设我在 Spring Boot 应用程序中有一个休息服务。 对于前端,我想登录我的应用程序,并且用户必须显示自己的信息,例如用户名、userFullName、birthDay 等。 首先用户必须获取令牌,然后用户必须通过两个不同的请求获取用户信息(用户名,userFullaname,birthDay)或者当用户获取令牌时用户必须在一个操作中获取它们?

比如下面的代码你可以看到我会返回token。

public static void addAuthentication(HttpServletResponse res, Authentication auth) 
    try 
        String concattedRoles = "";
        for (GrantedAuthority ga : auth.getAuthorities()) 
            if (!"".equals(concattedRoles)) 
                concattedRoles += "," + ga.getAuthority();
             else 
                concattedRoles += ga.getAuthority();
            

        

        String JWT = Jwts.builder().setSubject(auth.getName()).claim("roles", concattedRoles)
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
                .signWith(SignatureAlgorithm.HS512, SECRET).compact();
        res.addHeader(HEADER_STRING, TOKEN_PREFIX + " " + JWT);//add header
        res.getWriter().append("\"token\":\""+TOKEN_PREFIX + " " + JWT+"\"");//add body
    catch (Exception e)
        e.printStackTrace();
    

如果上面的代码我从数据库中获取用户信息作为下面的代码,这种方式是否正常?

@Autowired
UserRepository userRepository;
User user = (User)auth.getPrincipal();
String username = user.getUsername();
UserEntity userEntity = userRepository.findByUsername(username);

res.getWriter().append(userEntity);//关于之类的。

【问题讨论】:

这里的 User 和 UserEntity 有什么区别??..我的意思是 User user = (User)auth.getPrincipal();这条线本身你会得到一切。 如何从 User 类(公共类 User 实现 UserDetails、CredentialsContainer)中获取 userFullName、userbirthDay?我对这些操作的疑问必须是它们都是单独的操作还是什么? 检查一次***.com/a/20449938/6572971 【参考方案1】:

您需要做的“唯一”事情是创建自己的 UserDetailsService 实现,它返回您自己的 UserDetails 对象实现。

有关实现基于 JPA 的 UserDetailsService 的教程,请参阅 here。

答案改编自https://***.com/a/20350591/6572971

还可以在此线程上查看其他答案。

【讨论】:

每次我得到以下异常。 java.lang.ClassCastException:org.springframework.security.core.userdetails.User 无法转换为 com.example.notarydemo.model.UserTokenInfoObject【参考方案2】:

如果您确实想避免第二次检索用户信息的请求,您可以将用户的生日等添加到 JWT 令牌中的声明中。然后令牌本身包含您想了解的有关用户的所有信息,并且您不需要第二次访问数据库。

请注意,这也会增加令牌的大小,并使加密和解密花费更长的时间。

【讨论】:

【参考方案3】:

谢谢大家。 最后我解决了这个问题,如下所示。 我使用 org.springframework.security.core.userdetails 包中的 UserDetails、UserDetailsS​​ervice 接口。

package com.example.notarydemo.entity;

import com.fasterxml.jackson.annotation.JsonManagedReference;

import javax.persistence.*;
import java.util.Collection;
import java.util.List;

@Entity

@NamedStoredProcedureQueries(
        @NamedStoredProcedureQuery(name = "search_user",
                procedureName = "search_user",
                resultClasses = AppUser.class,
                parameters = 
                        @StoredProcedureParameter(mode = ParameterMode.IN, name = "id", type = Integer.class),
                        @StoredProcedureParameter(mode = ParameterMode.IN, name = "username", type = String.class),
                        @StoredProcedureParameter(mode = ParameterMode.IN, name = "enabled", type = String.class),
                        @StoredProcedureParameter(mode = ParameterMode.OUT, name = "cur", type = AppUser.class)
                ))
@Table(name = "APP_USER", schema = "MEHMAN")
public class AppUser 
    private long id;
    private String username;

    private String fulName;
    private String encrytedPassword;
    private long enabled;
    private Collection<UserRole> userRolesById;

    public AppUser(String userName, String fulName) 
        this.username = userName;
        this.fulName = fulName;
    

    public AppUser() 
    

    @Id
    @Column(name = "ID", nullable = false, precision = 0)
    public long getId() 
        return id;
    

    public void setId(long id) 
        this.id = id;
    

    @Basic
    @Column(name = "USER_NAME", nullable = false, length = 36)
    public String getUsername() 
        return username;
    

    public void setUsername(String userName) 
        this.username = userName;
    

    @Basic
    @Column(name = "FULLNAME", nullable = false, length = 45)
    public String getFULLNAME() 
        return fulName;
    

    public void setFULLNAME(String fullName) 
        this.fulName = fullName;
    

    @Basic
    @Column(name = "ENCRYTED_PASSWORD", nullable = false, length = 128)
    public String getEncrytedPassword() 
        return encrytedPassword;
    

    public void setEncrytedPassword(String encrytedPassword) 
        this.encrytedPassword = encrytedPassword;
    

    @Basic
    @Column(name = "ENABLED", nullable = false, precision = 0)
    public long getEnabled() 
        return enabled;
    

    public void setEnabled(long enabled) 
        this.enabled = enabled;
    

    @Override
    public boolean equals(Object o) 
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        AppUser appUser = (AppUser) o;

        if (id != appUser.id) return false;
        if (enabled != appUser.enabled) return false;
        if (username != null ? !username.equals(appUser.username) : appUser.username != null) return false;
        if (encrytedPassword != null ? !encrytedPassword.equals(appUser.encrytedPassword) : appUser.encrytedPassword != null)
            return false;

        return true;
    

    @Override
    public int hashCode() 
        int result = (int) (id ^ (id >>> 32));
        result = 31 * result + (username != null ? username.hashCode() : 0);
        result = 31 * result + (encrytedPassword != null ? encrytedPassword.hashCode() : 0);
        result = 31 * result + (int) (enabled ^ (enabled >>> 32));
        return result;
    

    @OneToMany(mappedBy = "appUserByUserId")
    @JsonManagedReference
    public Collection<UserRole> getUserRolesById() 
        return userRolesById;
    

    public void setUserRolesById(Collection<UserRole> userRolesById) 
        this.userRolesById = userRolesById;
    






package com.example.notarydemo.model;

import com.example.notarydemo.entity.AppUser;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;

public class MyUserPrincipal implements UserDetails 
    private AppUser user;

    public MyUserPrincipal(AppUser user) 
        System.out.println(user.getFULLNAME() + user.getUsername() + user.getEnabled());
        this.user = user;
    

    public AppUser getUser() 
        return user;
    

    public void setUser(AppUser user) 
        this.user = user;
    

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() 
        return null;
    

    @Override
    public String getPassword() 
        return user.getEncrytedPassword();
    

    @Override
    public String getUsername() 
        return user.getUsername();
    

    @Override
    public boolean isAccountNonExpired() 
        return true;
    

    @Override
    public boolean isAccountNonLocked() 
        return true;
    

    @Override
    public boolean isCredentialsNonExpired() 
        return true;
    

    @Override
    public boolean isEnabled() 
        if (user.getEnabled() == 1)
        return true;
        return false;
    






package com.example.notarydemo.config;

import com.example.notarydemo.entity.AppUser;
import com.example.notarydemo.model.MyUserPrincipal;
import com.example.notarydemo.model.UserTokenInfoObject;
import com.example.notarydemo.repository.AppUserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

@Service
public class MyUserDetailsService implements UserDetailsService 

    @Autowired
    private AppUserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 
            AppUser user = userRepository.findByUsername(username);
            if (user == null)
                throw new UsernameNotFoundException(username);
        return new MyUserPrincipal(user);
    






public static void addAuthentication(HttpServletResponse res, Authentication auth) 
        try 
            String concattedRoles = "";
            for (GrantedAuthority ga : auth.getAuthorities()) 
                if (!"".equals(concattedRoles)) 
                    concattedRoles += "," + ga.getAuthority();
                 else 
                    concattedRoles += ga.getAuthority();
                

            

            String JWT = Jwts.builder().setSubject(auth.getName()).claim("roles", concattedRoles)
                    .setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
                    .signWith(SignatureAlgorithm.HS512, SECRET).compact();
            res.addHeader(HEADER_STRING, TOKEN_PREFIX + " " + JWT);
           MyUserPrincipal user = (MyUserPrincipal) auth.getPrincipal();

            System.out.println(user.getUser().getFULLNAME());
            res.getWriter().append("\"token\":\""+TOKEN_PREFIX + " " + JWT+"\"");
        catch (Exception e)
            e.printStackTrace();
        
    

http://www.baeldung.com/spring-security-authentication-with-a-database

【讨论】:

以上是关于如何在 Spring Security 中获取 userInformation?的主要内容,如果未能解决你的问题,请参考以下文章

如何获取 Spring Security SessionRegistry?

如何在 Spring Security 中取消 cookie?

如何在Grails 2单元测试中获取spring security提供的currentUser

如何使用 Spring Security 在代码中获取用户的授权凭据?

如何在 Spring Security 中测试 AuthenticationPrincipal 并获取 ID 令牌?

如何使用spring security在grails中获取所有当前登录用户的列表(包括rememberme cookie)