登录时生成JWT令牌

时间:2018-02-21 00:15:08

标签: spring-boot jwt

如果提供的用户名密码准确,我想生成JWT。我有userdetailservice,我正在使用AbstractUserDetailsAuthenticationProvider。这是我的代码:

public class JwtAuthenticationTokenFilter extends AbstractAuthenticationProcessingFilter {


    public JwtAuthenticationTokenFilter() {
        super("/rest/**");
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest httpServletRequest,
                                                HttpServletResponse httpServletResponse)
            throws AuthenticationException, IOException, ServletException {

        String header = httpServletRequest.getHeader("Authorisation");

        if (header == null || !header.startsWith("Token")) {
            throw new RuntimeException("JWT Token is missing");
        }

        String authenticationToken  = header.substring(6);

        JwtAuthenticationToken token = new JwtAuthenticationToken(authenticationToken);

       return  getAuthenticationManager().authenticate(token);
    }

当我尝试登录时,即使密码错误也会返回JWT。

@RestController
@RequestMapping("/token")
public class TokenController {


    private JwtGenerator jwtGenerator;

    public TokenController(JwtGenerator jwtGenerator) {
        this.jwtGenerator = jwtGenerator;
    }

    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String createAuthenticationToken(
            @RequestBody User user,
            HttpServletResponse response) throws AuthenticationException, IOException {

        return jwtGenerator.generate(user);
    }

我的理解是当用户尝试登录时,用户详细信息服务通过用户名加载验证用户的身份,因此我不知道为什么它不起作用。

这是我的安全配置的一部分:

@Override
protected void configure(HttpSecurity http) throws Exception {

    http.csrf().disable()
            .authorizeRequests().antMatchers("**/rest/**").authenticated()
            .and()
            .exceptionHandling().authenticationEntryPoint(entryPoint)
            .and()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    http.addFilterBefore(authenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    http.headers().cacheControl();

}

1 个答案:

答案 0 :(得分:1)

您的问题是,当您调用请求登录时,您不是身份验证用户,您只是在创建令牌,而不是在检查密码是否有效,因此首先在登录服务中您必须添加以下代码: / p>

@RequestMapping(value = "/login", method = RequestMethod.POST)
public ResponseEntity<?> login(@RequestBody LoginUser loginUser) throws AuthenticationException {

    final Authentication authentication = authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(
                    loginUser.getUsername(),
                    loginUser.getPassword()
            )
    );
    SecurityContextHolder.getContext().setAuthentication(authentication);
    final String token = jwtTokenUtil.generateToken(authentication);
    User user = userService.getUserByUsername(loginUser.getUsername());
    user.setToken(token);
    return ResponseEntity.ok(user);
}

LoginUser是一个Java类,只有两个字段,用户名和密码带有构造函数,这两个字段的获取器和设置器。

final Authentication authentication = authenticationManager.authenticate(
        new UsernamePasswordAuthenticationToken(
                loginUser.getUsername(),
                loginUser.getPassword()
        )
);

此代码将检查用户名和密码的有效性,它将自身转到userdetails类中定义的loadbyusername函数,如果用户名或密码错误,api将返回错误的凭据错误,但为此您需要编写额外的代码。

创建课程:

@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, 
Serializable {

    @Override
    public void commence(HttpServletRequest request,
                     HttpServletResponse response,
                     AuthenticationException authException) throws IOException {

    response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}

,然后在安全配置类中的JwtAuthenticationEntryPoint类的初始化对象之后,如下所示:

@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;

并将此代码添加到Web安全配置类的configure函数中:

.exceptionHandling().authenticationEntryPoint(unauthorizedHandler)