空@AuthenticationPrincipal用户

时间:2018-08-04 20:04:33

标签: java spring spring-mvc spring-security

我想用JWT保护REST服务器。为此,我使用this tutorial。一切正常,除了一件事-当用户已经登录但我要在私有控制器中获得授权用户,但是getUserInfo方法接收到等于null的用户。

这是私有控制器AccountController:

@RestController
@RequestMapping("/private")
public class AccountController {

    @GetMapping("/getUserInfo")
    public @ResponseBody
    String getUserInfo(@AuthenticationPrincipal final UserDetails user) {// user == null
        return user.getUsername();
    }
}

WebSecurity:

@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
    private AccountDetailsServiceImpl accountDetailsService;
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    public WebSecurity(AccountDetailsServiceImpl accountDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
        this.accountDetailsService = accountDetailsService;
        this.bCryptPasswordEncoder = bCryptPasswordEncoder;
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable().authorizeRequests()
                .antMatchers(HttpMethod.POST, SIGN_UP_URL).permitAll()
                .anyRequest().authenticated()
                .and()
                .addFilter(new JWTAuthenticationFilter(authenticationManager()))
                .addFilter(new JWTAuthorizationFilter(authenticationManager()))
                // this disables session creation on Spring Security
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

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

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
        return source;
    }
}

AccountDetailsS​​erviceImpl:

@Service
public class AccountDetailsServiceImpl implements UserDetailsService {
    private AccountRepository applicationUserRepository;

    public AccountDetailsServiceImpl(AccountRepository applicationUserRepository) {
        this.applicationUserRepository = applicationUserRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Optional<Account> applicationUser = applicationUserRepository.findByUsername(username);
        if (applicationUser == null) {
            throw new UsernameNotFoundException(username);
        }
        User user = new User(applicationUser.get().getUsername(), applicationUser.get().getPassword(), emptyList());
        return user;
    }
}

帐户:

@Entity(name = "Account")
@Table(name = "account")
public class Account implements UserDetails {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;

    private String username;

    private String password;


    private Account() { }

    public Account(final String username, final String password) {
        this.username = username;
        this.password = password;
    }


    @Override
    public Collection<GrantedAuthority> getAuthorities() {
        return new ArrayList<>();
    }

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

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

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

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

    public Long getId() {
        return id;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public String getPassword() {
        return password;
    }

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

那是什么问题,如何使用AuthenticationPrincipal获得授权用户?

UPD:

我尝试使用

String getUserInfo(@AuthenticationPrincipal final Object user)

在我的AccountController中(我将user的类型更改为Object),并得到了不是空对象。之后,我尝试使用user.getClass()获得真实的对象类型并得到String。接下来,我尝试将user签名中的参数String的类型更改为getUserInfo,并用用户名获得了String。因此,我可以获得用户信息,但类型不合适。我也尝试使用Account类型,但也得到了null

因此,现在的主要问题是如何使用user获得Account类型的@AuthenticationPrincipal

UPD2:

现在我也意识到getUserInfo获得了UsernamePasswordAuthenticationToken对象,所以我认为我需要更改JWTAuthorizationFilter,但是SecurityContextHolder.getContext().setAuthentication()是否需要{{1 }}?

UPD3:

JWTAuthorizationFilter:

UsernamePasswordAuthenticationToken

UPD4:

JWTAuthenticationFilter.doFilterInternal():

public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

    public JWTAuthorizationFilter(AuthenticationManager authManager) {
        super(authManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest req,
                                    HttpServletResponse res,
                                    FilterChain chain) throws IOException, ServletException {
        String header = req.getHeader(HEADER_STRING);

        if (header == null || !header.startsWith(TOKEN_PREFIX)) {
            chain.doFilter(req, res);
            return;
        }

        UsernamePasswordAuthenticationToken authentication = getAuthentication(req);

        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(req, res);
    }

    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
        String token = request.getHeader(HEADER_STRING);
        if (token != null) {
            // parse the token.

            String user = Jwts.parser().setSigningKey(KEY).parseClaimsJws(token.replace(TOKEN_PREFIX, "")).getBody().getSubject();


            if (user != null) {
                return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
            }
            return null;
        }
        return null;
    }
}

此方法的更新版本抛出@Override protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException { String header = req.getHeader(HEADER_STRING); if (header == null || !header.startsWith(TOKEN_PREFIX)) { chain.doFilter(req, res); return; } UsernamePasswordAuthenticationToken authentication = getAuthentication(req); authentication.setDetails(authenticationDetailsSource.buildDetails(req)); Authentication authResult = getAuthenticationManager().authenticate(authentication); //BadCredentialsException: Bad credentials SecurityContextHolder.getContext().setAuthentication(authResult); chain.doFilter(req, res); }

0 个答案:

没有答案