本文介绍了Spring Security不返回UserDetails对象,仅返回用户名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我以为我的授权实现已经完成,但是当尝试检索UserDetails对象时,我得到的只是用户名.

I had thought that my authorization implementation was done but when attempting to retrieve the UserDetails object, all I'm getting is the username.

我正在使用具有以下详细信息的oauth.

I'm using oauth with the following particulars.

配置AuthenticationManager:

Configuring the AuthenticationManager:

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

完成此操作后,我可以调试到我的userDetailsS​​ervice中:

With this done, I can debug into my userDetailsService:

@Service
public class UserServiceImpl implements UserService, UserDetailsService {
@Override
    public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
        MyUser persistedUser = userRepository.findByEmail(email);

        if (persistedUser == null) {
            throw new UsernameNotFoundException(String.format("The email %s doesn't exist", email));
        }

        List<GrantedAuthority> authorities = new ArrayList<>();

        MyUser inMemoryUser = new MyUser(persistedUser.getEmail(), null, persistedUser.getEnabled(), false,
                false, false, authorities);

        return inMemoryUser;
    }
}

这一切都很好,我的客户取回了JWT.但是在调试以后的控制器方法时,发现了以下问题.

This completes fine and my client gets back the JWT. But I found the following problem when debugging a later controller method.

@GetMapping
public @ResponseBody Iterable<Curriculum> getMyCurriculums(@AuthenticationPrincipal MyUser injectedUser) {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    MyUser principle = (MyUser) auth.getPrincipal();
    return curriculumService.findByUser(principle);
}

在这种情况下,injectedUser = null,auth是OAuth2Authentication,principal是String-用户名.应该是MyUser

In this case, injectedUser = null, auth is an OAuth2Authentication, and principle is a String - the username. It should be MyUser

推荐答案

您应该配置Spring Security将jwt令牌解码为MyUser对象.

You should configure Spring Security to decode jwt token into MyUser object.

首先定义一个自定义OAuth2Authentication来封装MyUser.

First define a custom OAuth2Authentication to encapsulate MyUser.

public class OAuth2AuthenticationUser extends OAuth2Authentication {

    private MyUser myUser;

    public OAuth2AuthenticationUser(OAuth2Request storedRequest, Authentication userAuthentication) {
        super(storedRequest, userAuthentication);
    }

    public MyUser getMyUser() {
        return myUser;
    }

    public void setMyUser(MyUser) {
        this.myUser= myUser;
    }
}

然后在安全配置"类中按如下方式配置jwt令牌解码:

Then in a Security Configuration class configure jwt token decoding as follows:

@Bean
public JwtAccessTokenConverter accessTokenConverter() {
    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setSigningKey("SIGNING_KEY");
    converter.setAccessTokenConverter(getAuthenticationAccessTokenConverter());
    return converter;
}

private DefaultAccessTokenConverter getAuthenticationAccessTokenConverter() {
    return new DefaultAccessTokenConverter() {
        @Override
        public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
            OAuth2Authentication authentication = (OAuth2Authentication) super.extractAuthentication(map);

            OAuth2AuthenticationUser authenticationUser =
                    new OAuth2AuthenticationUser(authentication.getOAuth2Request(), authentication.getUserAuthentication());

            MyUser myUser = new MyUser();

            // Example properties
            myUser.setId(map.get("id") != null ? Long.valueOf(map.get("id").toString()) : null);
            myUser.setUsername(map.get("user_name") != null ? map.get("user_name").toString() : null);
            myUser.setFullName(map.get("fullName") != null ? map.get("fullName").toString() : null);
            myUser.setCustomerId(map.get("customerId") != null ? Long.valueOf(map.get("customerId").toString()) : null);
            myUser.setCustomerName(map.get("customerName") != null ? map.get("customerName").toString() : null);

            // More other properties

            authenticationUser.setMyUser(myUser);

            return authenticationUser;
        }
    };
}

然后您可以从Spring Security上下文中访问MyUser对象,如下所示:

And then you have access to MyUser object from Spring Security context as follows:

private static MyUser getMyUser() {
    OAuth2AuthenticationUser authentication = (OAuth2AuthenticationUser) SecurityContextHolder.getContext().getAuthentication();
    return (authentication != null && authentication.getMyUser() != null ? authentication.getMyUser() : new MyUser());
}

这非常适合无状态环境,因为最大限度地减少了对用户详细信息的数据库访问,而您只需要jwt令牌.

This fits well in a stateless environment as database access for user details is minimized and all you need is jwt token.

这篇关于Spring Security不返回UserDetails对象,仅返回用户名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-22 08:48