JWT如何与Spring MVC一起使用来创建令牌和validation令牌?

我实际上希望对JWT概念以及它如何与Spring MVC工作有更多更清楚的理解。 我找到了链接https://github.com/nielsutrecht/jwt-angular-spring ,其程序运行得非常好。 但我想知道它如何创建令牌,然后用户如何登录应用程序。 我需要澄清/回答它是如何工作的? 请做好。

我的理解:在我看来,当你启动应用程序时,将调用GenericFilterBean实现类,它将生成JWT令牌并将其发送到本地存储中的UI(不确定),然后此令牌将带有请求和标头然后它将得到validation,并将访问给用户?

我想把一些代码片段作为参考(即使你可以从提到的链接中查找代码)

AuthenticationTokenProcessingFilter.java

 public class AuthenticationTokenProcessingFilter extends GenericFilterBean { private final UserDetailsService userService; public AuthenticationTokenProcessingFilter(UserDetailsService userService){ this.userService = userService; } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,ServletException{ HttpServletRequest httpRequest = this.getAsHttpRequest(request); String authToken = this.extractAuthTokenFromRequest(httpRequest); String userName = TokenUtils.getUserNameFromToken(authToken); if (userName != null) { UserDetails userDetails = this.userService.loadUserByUsername(userName); if (TokenUtils.validateToken(authToken, userDetails)) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest)); SecurityContextHolder.getContext().setAuthentication(authentication); } } chain.doFilter(request, response); } private HttpServletRequest getAsHttpRequest(ServletRequest request){ if (!(request instanceof HttpServletRequest)) { throw new RuntimeException("Expecting an HTTP request"); } return (HttpServletRequest) request; } private String extractAuthTokenFromRequest(HttpServletRequest httpRequest){ /* Get token from header */ String authToken = httpRequest.getHeader("X-Auth-Token"); System.out.println("AUTH TOKEN : "+authToken); /* If token not found get it from request parameter */ if (authToken == null) { authToken = httpRequest.getParameter("token"); } return authToken; } } 

TokenUtils.java

 public class TokenUtils{ public static final String MAGIC_KEY = "obfuscate"; public static String createToken(UserDetails userDetails){ System.out.println(" ----- Create Token ------"); /* Expires in one hour */ long expires = System.currentTimeMillis() + 1000L * 60 * 60; StringBuilder tokenBuilder = new StringBuilder(); tokenBuilder.append(userDetails.getUsername()); tokenBuilder.append(":"); tokenBuilder.append(expires); tokenBuilder.append(":"); tokenBuilder.append(TokenUtils.computeSignature(userDetails, expires)); return tokenBuilder.toString(); } public static String computeSignature(UserDetails userDetails, long expires){ System.out.println("------ Compute Signature ------"); StringBuilder signatureBuilder = new StringBuilder(); signatureBuilder.append(userDetails.getUsername()); signatureBuilder.append(":"); signatureBuilder.append(expires); signatureBuilder.append(":"); signatureBuilder.append(userDetails.getPassword()); signatureBuilder.append(":"); signatureBuilder.append(TokenUtils.MAGIC_KEY); MessageDigest digest; try { digest = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { throw new IllegalStateException("No MD5 algorithm available!"); } System.out.println(new String(Hex.encode(digest.digest(signatureBuilder.toString().getBytes())))); return new String(Hex.encode(digest.digest(signatureBuilder.toString().getBytes()))); } public static String getUserNameFromToken(String authToken){ System.out.println("----- Get Username From TOken ----"); if (null == authToken) { return null; } String[] parts = authToken.split(":"); return parts[0]; } public static boolean validateToken(String authToken, UserDetails userDetails) { System.out.println("=== Validate Token ==="); String[] parts = authToken.split(":"); long expires = Long.parseLong(parts[1]); String signature = parts[2]; if (expires < System.currentTimeMillis()) { return false; } System.out.println(signature.equals(TokenUtils.computeSignature(userDetails, expires))); return signature.equals(TokenUtils.computeSignature(userDetails, expires)); } } 

的context.xml

       classpath:database.properties                                                           

编辑-1:

 AUTH TOKEN : null ----- Get Username From Token ---- Jan 01, 2016 2:35:01 AM com.sun.jersey.spi.container.servlet.WebComponent filterFormParameters WARNING: A servlet request, to the URI http://localhost:8080/angular-rest-security/rest/user/authenticate, contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using @FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected. Hibernate: select user0_.id as id1_1_, user0_.name as name2_1_, user0_.password as password3_1_ from User user0_ where user0_.name=? Hibernate: select roles0_.User_id as User_id1_1_0_, roles0_.roles as roles2_2_0_ from User_roles roles0_ where roles0_.User_id=? Hibernate: select user0_.id as id1_1_, user0_.name as name2_1_, user0_.password as password3_1_ from User user0_ where user0_.name=? Hibernate: select roles0_.User_id as User_id1_1_0_, roles0_.roles as roles2_2_0_ from User_roles roles0_ where roles0_.User_id=? ----- Create Token ------ ------ Compute Signature ------ 525b8e635bb234684d2a02b99f38d687 AUTH TOKEN : null ----- Get Username From Token ---- Jan 01, 2016 2:36:27 AM com.sun.jersey.spi.container.servlet.WebComponent filterFormParameters WARNING: A servlet request, to the URI http://localhost:8080/angular-rest-security/rest/user/authenticate, contains form parameters in the request body but the request body has been consumed by the servlet or a servlet filter accessing the request parameters. Only resource methods using @FormParam will work as expected. Resource methods consuming the request body by other means will not work as expected. AUTH TOKEN : admin:1451599569652:525b8e635bb234684d2a02b99f38d687 ----- Get Username From Token ---- Hibernate: select user0_.id as id1_1_, user0_.name as name2_1_, user0_.password as password3_1_ from User user0_ where user0_.name=? Hibernate: select roles0_.User_id as User_id1_1_0_, roles0_.roles as roles2_2_0_ from User_roles roles0_ where roles0_.User_id=? Hibernate: select user0_.id as id1_1_, user0_.name as name2_1_, user0_.password as password3_1_ from User user0_ where user0_.name=? Hibernate: select roles0_.User_id as User_id1_1_0_, roles0_.roles as roles2_2_0_ from User_roles roles0_ where roles0_.User_id=? === Validate Token === ------ Compute Signature ------ 525b8e635bb234684d2a02b99f38d687 true ------ Compute Signature ------ 525b8e635bb234684d2a02b99f38d687 Hibernate: select user0_.id as id1_1_, user0_.name as name2_1_, user0_.password as password3_1_ from User user0_ where user0_.name=? Hibernate: select roles0_.User_id as User_id1_1_0_, roles0_.roles as roles2_2_0_ from User_roles roles0_ where roles0_.User_id=? ----- Create Token ------ ------ Compute Signature ------ b6238344022f3f4dd3787f0f8fa99b44 AUTH TOKEN : null ----- Get Username From Token ---- AUTH TOKEN : admin:1451599596826:b6238344022f3f4dd3787f0f8fa99b44 ----- Get Username From Token ---- Hibernate: select user0_.id as id1_1_, user0_.name as name2_1_, user0_.password as password3_1_ from User user0_ where user0_.name=? Hibernate: select roles0_.User_id as User_id1_1_0_, roles0_.roles as roles2_2_0_ from User_roles roles0_ where roles0_.User_id=? === Validate Token === ------ Compute Signature ------ b6238344022f3f4dd3787f0f8fa99b44 true ------ Compute Signature ------ b6238344022f3f4dd3787f0f8fa99b44 AUTH TOKEN : admin:1451599596826:b6238344022f3f4dd3787f0f8fa99b44 ----- Get Username From Token ---- Hibernate: select user0_.id as id1_1_, user0_.name as name2_1_, user0_.password as password3_1_ from User user0_ where user0_.name=? Hibernate: select roles0_.User_id as User_id1_1_0_, roles0_.roles as roles2_2_0_ from User_roles roles0_ where roles0_.User_id=? === Validate Token === ------ Compute Signature ------ b6238344022f3f4dd3787f0f8fa99b44 true ------ Compute Signature ------ b6238344022f3f4dd3787f0f8fa99b44 02:36:38,728 INFO NewsEntryResource.list():49 - list() Hibernate: select newsentry0_.id as id1_0_, newsentry0_.content as content2_0_, newsentry0_.date as date3_0_ from NewsEntry newsentry0_ order by newsentry0_.date desc AUTH TOKEN : null ----- Get Username From Token ---- 

我是你给的链接( https://github.com/nielsutrecht/jwt-angular-spring )的作者。

示例应用程序使用Jjwt库来创建和解密JSON Web令牌。 在我的示例应用程序中,当一个人成功登录时创建令牌。 这发生在UserController.java中的login()方法中。 成功登录(示例应用程序不处理像密码这样的愚蠢的东西)以返回带有此令牌的LoginResponse 。 角度应用程序将此设置为随每个请求一起发送的默认标头。 如果您不希望在按F5后再次登录,则可以将其存储在本地存储或cookie中。 再次; 这是一个让事情尽可能简单的例子; 我故意把这些东西丢了。

标头由JwtFilter类读取并存储在请求上下文中。 这样,任何路径都可以访问此信息,而无需解密标头本身。

虽然在相应的博客文章中对所有内容都进行了深入解释:如果有任何您不理解的内容,请告诉我。

当您执行登录时,您通过HTTP post请求发送用户名和密码。 如果凭据正确,Java Web服务将使用令牌进行响应。 前端AngularJS应用程序将令牌存储到LocalStorage或Cookie中。 在您发出的每个下一个请求时,令牌将作为Authorization标头的值发送。 Java Web服务将拦截请求并检查令牌的存在性和有效性。

您也可以查看我制作的这个演示应用程序 。