如何从jHipster中的SecurityContextHolder检索自定义UserDetails?

时间:2019-04-20 22:34:05

标签: spring-security jhipster

我是jHipster的新手,我正尝试将用户与公司ID相关联,以根据所述公司ID限制他们有权访问的实体。

我希望能够使用SecurityContext存储我的UserDetails的自定义实现。 我已按照这封信进行了多次教程,但似乎无法正常运行:SecurityContext返回的对象始终为org.springframework.security.core.userdetails.User类型,因此无法将其转换为实现的UserDetails类

DomainUserDetailsS​​ervice.java

@Service("domainUserDetailsService")
public class DomainUserDetailsService implements UserDetailsService {

    private final Logger log = LoggerFactory.getLogger(DomainUserDetailsService.class);

    private  UserRepository userRepository;

    public DomainUserDetailsService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    @Transactional(readOnly = true)
    public UserDetails loadUserByUsername(final String login) {
        log.debug("Authenticating {}", login);

        User user = userRepository.findOneWithAuthoritiesByEmail(login).get();

        return new UserDetails(user, 22L);
    }

UserDetails.java

public class UserDetails implements org.springframework.security.core.userdetails.UserDetails {
    private User user;
    private Long companyId = 0L;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Long getCompanyId() {
        return companyId;
    }

    public void setCompanyId(Long companyId) {
        this.companyId = companyId;
    }

    public UserDetails(User user, Long companyId) {
        this.user = user;
        this.companyId = companyId;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return user.getAuthorities().stream().map(authority -> new SimpleGrantedAuthority(authority.getName().toString())).collect(Collectors.toList());
    }

    public Long getId() {
        return user.getId();
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getLogin();
    }

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

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

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

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

    public User getUserDetails() {
        return user;
    }
}

SecurityConfiguration.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Import(SecurityProblemSupport.class)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    private final AuthenticationManagerBuilder authenticationManagerBuilder;

    private final UserDetailsService userDetailsService;

    private final TokenProvider tokenProvider;

    private final CorsFilter corsFilter;

    private final SecurityProblemSupport problemSupport;

    public SecurityConfiguration(AuthenticationManagerBuilder authenticationManagerBuilder, @Qualifier("domainUserDetailsService") UserDetailsService userDetailsService, TokenProvider tokenProvider, CorsFilter corsFilter, SecurityProblemSupport problemSupport) {
        this.authenticationManagerBuilder = authenticationManagerBuilder;
        this.userDetailsService = userDetailsService;
        this.tokenProvider = tokenProvider;
        this.corsFilter = corsFilter;
        this.problemSupport = problemSupport;
    }


    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

 @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
......

SecurityUtils.java

public static UserDetails getCurrentUserDetail() {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        Authentication authentication = securityContext.getAuthentication();
        if (authentication != null) {
            if (authentication.getPrincipal() instanceof UserDetails) {
                UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
                return springSecurityUser;
            }
        }
        return null;
    }

问题在于,在SecurityUtils中,authentication.getPrincipal()。getClass()始终属于类 org.springframework.security.core.userdetails.User 。 我希望它的类型为 UserDetails

编辑 代码确实通过DomainUserDetailsS​​ervice,正如我在日志中看到的那样。

我相信问题与 createToken 期间TokenProvider.java中的身份验证有关,在UserJWTController.java

中进行用户身份验证时会调用

2 个答案:

答案 0 :(得分:0)

您应该覆盖configure(AuthenticationManagerBuilder auth),而不是@Autowired public void configureGlobal

 @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

答案 1 :(得分:0)

我也遇到了同样的问题,我通过对TokenProvider.createToken和TokenProvider.getAuthentication方法进行了一些更新来处理它。想法是在 createToken 方法中将租户(在您的情况下为公司)ID或任何其他变量保存在JWT Token中,然后在 getAuthentication 方法中提取它们。下面是我的方法的代码:

Registering
Registered
all_done()

现在我们可以从JWT令牌中获取这些变量

public String createToken(Authentication authentication, boolean rememberMe, String channel) {
        String authorities = authentication.getAuthorities().stream()
            .map(GrantedAuthority::getAuthority)
            .collect(Collectors.joining(","));

        long now = (new Date()).getTime();
        Date validity;
        if (rememberMe) {
            validity = new Date(now + this.tokenValidityInMillisecondsForRememberMe);
        } else {
            validity = new Date(now + this.tokenValidityInMilliseconds);
        }

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        Long userPkId = null;
        Long tenantId = null;

        if (auth != null) {
            Object principal = auth.getPrincipal();

            if (principal instanceof DomainUserDetails) {
                DomainUserDetails domainUserDetails = (DomainUserDetails) principal;
                tenantId = domainUserDetails.getTenantId();
                userPkId = domainUserDetails.getId();
            }
        }

        return Jwts.builder()
            .setSubject(authentication.getName())
            .claim(AUTHORITIES_KEY, authorities)
            .claim(USER_ID_KEY, userPkId)
            .claim(TENANT_KEY, tenantId)
            .claim(CHANNEL_KEY, channel)
            .signWith(key, SignatureAlgorithm.HS512)
            .setExpiration(validity)
            .compact();
    }