{"id":325,"date":"2022-06-13T08:20:18","date_gmt":"2022-06-12T23:20:18","guid":{"rendered":"https:\/\/www.kd2.jp\/memo3\/?p=325"},"modified":"2022-08-15T10:31:19","modified_gmt":"2022-08-15T01:31:19","slug":"spring-restful-jwt","status":"publish","type":"post","link":"https:\/\/www.kd2.jp\/memo3\/?p=325","title":{"rendered":"Spring + RESTful + JWT"},"content":{"rendered":"<p><a href=\"https:\/\/datatracker.ietf.org\/doc\/html\/rfc7519\">RFC7519 : JWT<\/a><\/p>\n<p>pom.xml<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">&lt;dependency&gt;\r\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;spring-boot-starter&lt;\/artifactId&gt;\r\n&lt;\/dependency&gt;\r\n\r\n&lt;dependency&gt;\r\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;spring-boot-starter-test&lt;\/artifactId&gt;\r\n    &lt;scope&gt;test&lt;\/scope&gt;\r\n&lt;\/dependency&gt;\r\n\r\n&lt;!-- \u8ffd\u52a0 --&gt;\r\n&lt;dependency&gt;\r\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt; \r\n    &lt;artifactId&gt;spring-boot-starter-web&lt;\/artifactId&gt; \r\n&lt;\/dependency&gt; \r\n&lt;dependency&gt;\r\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt; \r\n    &lt;artifactId&gt;spring-boot-starter-security&lt;\/artifactId&gt; \r\n&lt;\/dependency&gt;\r\n&lt;dependency&gt; \r\n    &lt;groupId&gt;io.jsonwebtoken&lt;\/groupId&gt; \r\n    &lt;artifactId&gt;jjwt&lt;\/artifactId&gt; \r\n    &lt;version&gt;0.9.1&lt;\/version&gt; \r\n&lt;\/dependency&gt;\r\n&lt;dependency&gt; \r\n    &lt;groupId&gt;javax.xml.bind&lt;\/groupId&gt; \r\n    &lt;artifactId&gt;jaxb-api&lt;\/artifactId&gt; \r\n&lt;\/dependency&gt; \r\n&lt;dependency&gt;\r\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;spring-boot-devtools&lt;\/artifactId&gt;\r\n&lt;\/dependency&gt;\r\n\r\n&lt;dependency&gt;\r\n    &lt;groupId&gt;junit&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;junit&lt;\/artifactId&gt;\r\n    &lt;scope&gt;test&lt;\/scope&gt;\r\n&lt;\/dependency&gt;\r\n&lt;dependency&gt;\r\n    &lt;groupId&gt;org.junit.jupiter&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;junit-jupiter-api&lt;\/artifactId&gt;\r\n    &lt;scope&gt;test&lt;\/scope&gt;\r\n&lt;\/dependency&gt;\r\n&lt;dependency&gt;\r\n    &lt;groupId&gt;org.junit.jupiter&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;junit-jupiter-engine&lt;\/artifactId&gt;\r\n    &lt;scope&gt;test&lt;\/scope&gt;\r\n&lt;\/dependency&gt;\r\n&lt;dependency&gt;\r\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\r\n    &lt;artifactId&gt;spring-boot-test-autoconfigure&lt;\/artifactId&gt;\r\n    &lt;scope&gt;test&lt;\/scope&gt;\r\n&lt;\/dependency&gt;<\/pre>\n<\/div>\n<p>application.properties<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">secret=somerandomsecret<\/pre>\n<\/div>\n<p>main<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">package jp.kd2.jwttest;\r\n\r\nimport org.springframework.boot.SpringApplication;\r\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\r\n\r\n@SpringBootApplication\r\npublic class JwttestApplication {\r\n\r\n    public static void main(String[] args) {\r\n        SpringApplication.run(JwttestApplication.class, args);\r\n    }\r\n\r\n}<\/pre>\n<\/div>\n<p>RequestModel<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">package jp.kd2.jwttest.model;\r\n\r\nimport java.io.Serializable;\r\n\r\npublic class JwtRequest implements Serializable {\r\n    \r\n    private static final long serialVersionUID = 1L; \r\n   \r\n       private String username; \r\n   \r\n       private String password; \r\n   \r\n       public JwtRequest() { \r\n       } \r\n   \r\n       public JwtRequest(String username, String password) { \r\n           super(); \r\n           this.username = username; this.password = password; \r\n       } \r\n   \r\n       public String getUsername() { \r\n           return username;\r\n       } \r\n   \r\n       public void setUsername(String username) { \r\n           this.username = username; \r\n       } \r\n   \r\n       public String getPassword() { \r\n           return password; \r\n       } \r\n   \r\n       public void setPassword(String password) {\r\n           this.password = password; \r\n       }\r\n}\r\n<\/pre>\n<\/div>\n<p>ResponseModel<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">package jp.kd2.jwttest.model;\r\n\r\nimport java.io.Serializable;\r\n\r\npublic class JwtResponse implements Serializable {\r\n    \r\n    private static final long serialVersionUID = 1L;\r\n    \r\n    private final String token;\r\n    \r\n    public JwtResponse(String token) {\r\n        this.token = token;\r\n    }\r\n    \r\n    public String getToken() {\r\n        return token;\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>RestController<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">package jp.kd2.jwttest.controller;\r\n\r\nimport org.springframework.web.bind.annotation.GetMapping;\r\nimport org.springframework.web.bind.annotation.RestController;\r\n\r\n@RestController \r\npublic class HelloWorldController {\r\n\r\n    @GetMapping(\"\/hello\") \r\n    public String hello() { \r\n        return \"{ \\\"greeting\\\" : \\\"Hello World Rest\\\" }\"; \r\n    } \r\n}<\/pre>\n<\/div>\n<p>JWTController<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">package jp.kd2.jwttest.controller;\r\n\r\nimport org.springframework.beans.factory.annotation.Autowired;\r\nimport org.springframework.http.ResponseEntity;\r\nimport org.springframework.security.authentication.AuthenticationManager;\r\nimport org.springframework.security.authentication.BadCredentialsException;\r\nimport org.springframework.security.authentication.DisabledException;\r\nimport org.springframework.security.authentication.UsernamePasswordAuthenticationToken;\r\nimport org.springframework.security.core.userdetails.UserDetails;\r\nimport org.springframework.web.bind.annotation.CrossOrigin;\r\nimport org.springframework.web.bind.annotation.PostMapping;\r\nimport org.springframework.web.bind.annotation.RequestBody;\r\nimport org.springframework.web.bind.annotation.RestController;\r\nimport jp.kd2.jwttest.service.JwtUserDetailsService;\r\nimport jp.kd2.jwttest.model.JwtRequest;\r\nimport jp.kd2.jwttest.model.JwtResponse;\r\nimport jp.kd2.jwttest.util.JwtTokenManager;\r\n\r\n@RestController\r\n@CrossOrigin\r\npublic class JwtController {\r\n\r\n    @Autowired\r\n    private JwtUserDetailsService userDetailsService;\r\n   \r\n    @Autowired\r\n    private AuthenticationManager authenticationManager;\r\n   \r\n    @Autowired\r\n    private JwtTokenManager tokenManager;\r\n   \r\n    @PostMapping(\"\/login\")\r\n    public ResponseEntity&lt;?&gt; createToken(\r\n            @RequestBody JwtRequest request) throws Exception {\r\n     \r\n        try {\r\n            authenticationManager.authenticate(\r\n                    new UsernamePasswordAuthenticationToken(\r\n                            request.getUsername(), request.getPassword()\r\n                    )\r\n            );\r\n        } catch (DisabledException e) {\r\n            throw new Exception(\"USER_DISABLED\", e);\r\n        } catch (BadCredentialsException e) {\r\n            throw new Exception(\"INVALID_CREDENTIALS\", e);\r\n        }\r\n        \r\n        final UserDetails userDetails = userDetailsService.loadUserByUsername(request.getUsername());\r\n        final String jwtToken = tokenManager.generateJwtToken(userDetails);\r\n        \r\n        return ResponseEntity.ok(new JwtResponse(jwtToken));\r\n   }\r\n}<\/pre>\n<\/div>\n<p>SecurityConfig<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">package jp.kd2.jwttest.config;\r\n\r\nimport org.springframework.beans.factory.annotation.Autowired;\r\nimport org.springframework.context.annotation.Bean;\r\nimport org.springframework.context.annotation.Configuration;\r\nimport org.springframework.security.authentication.AuthenticationManager;\r\nimport org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;\r\nimport org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;\r\nimport org.springframework.security.config.annotation.web.builders.HttpSecurity;\r\nimport org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;\r\nimport org.springframework.security.config.http.SessionCreationPolicy;\r\nimport org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;\r\nimport org.springframework.security.crypto.password.PasswordEncoder;\r\nimport org.springframework.security.web.SecurityFilterChain;\r\nimport org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;\r\nimport org.springframework.web.servlet.config.annotation.CorsRegistry;\r\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurer;\r\n\r\nimport jp.kd2.jwttest.util.JwtAuthenticationEntryPoint;\r\nimport jp.kd2.jwttest.util.JwtFilter; \r\n\r\n@Configuration\r\n@EnableWebSecurity\r\n@EnableGlobalMethodSecurity(prePostEnabled = true)\r\npublic class JwtSecurityConfig {\r\n    \r\n   @Autowired\r\n   private JwtAuthenticationEntryPoint authenticationEntryPoint;\r\n      \r\n   @Autowired\r\n   private JwtFilter filter;\r\n      \r\n   @Bean\r\n   public PasswordEncoder passwordEncoder() {\r\n      return new BCryptPasswordEncoder();\r\n   }\r\n   \r\n   @Bean\r\n   public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {\r\n       return authenticationConfiguration.getAuthenticationManager();\r\n   }\r\n   \r\n   @Bean\r\n   public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {\r\n             \r\n       http.cors().and().csrf().disable()\r\n       .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and()\r\n       .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()\r\n       .authorizeRequests()\r\n       .antMatchers(\"\/login\").permitAll()\r\n       .anyRequest().authenticated();\r\n       \r\n       http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);\r\n\r\n       return http.build();\r\n   }\r\n   \r\n   @Bean\r\n   public WebMvcConfigurer corsConfigurer() {\r\n       return new WebMvcConfigurer() {\r\n           @Override\r\n           public void addCorsMappings(CorsRegistry registry) {\r\n               registry.addMapping(\"\/**\").allowedMethods(\"*\");\r\n           }\r\n       };\r\n   }   \r\n}<\/pre>\n<\/div>\n<p>Service<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">package jp.kd2.jwttest.service;\r\n\r\nimport java.util.ArrayList; \r\nimport org.springframework.security.core.userdetails.User; \r\nimport org.springframework.security.core.userdetails.UserDetails; \r\nimport org.springframework.security.core.userdetails.UserDetailsService; \r\nimport org.springframework.security.core.userdetails.UsernameNotFoundException; \r\nimport org.springframework.stereotype.Service; \r\n\r\n@Service\r\npublic class JwtUserDetailsService implements UserDetailsService { \r\n    \r\n    @Override \r\n    public UserDetails loadUserByUsername(String username)\r\n        throws UsernameNotFoundException {\r\n       \r\n       if (\"jwtuser\".equals(username)) { \r\n           return new User(\"jwtuser\", \r\n                   \"$2a$10$Ik4eh\/jP3VBumhbcCfonseroGTrL1brrSBirm3aOXWJB09N9734\/i\",\r\n                   new ArrayList&lt;&gt;()); \r\n       } else { \r\n           throw new UsernameNotFoundException(\"User was not found : \" + username); \r\n       } \r\n    } \r\n}<\/pre>\n<\/div>\n<p>EntryPoint<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">package jp.kd2.jwttest.util;\r\n\r\nimport java.io.IOException;\r\nimport java.io.Serializable;\r\nimport javax.servlet.ServletException;\r\nimport javax.servlet.http.HttpServletRequest;\r\nimport javax.servlet.http.HttpServletResponse;\r\nimport org.springframework.security.core.AuthenticationException;\r\nimport org.springframework.security.web.AuthenticationEntryPoint;\r\nimport org.springframework.stereotype.Component;\r\n\r\n@Component\r\npublic class JwtAuthenticationEntryPoint\r\n    implements AuthenticationEntryPoint, Serializable {\r\n    \r\n    @Override\r\n    public void commence(\r\n            HttpServletRequest request, \r\n            HttpServletResponse response, \r\n            AuthenticationException authException)\r\n                    throws IOException, ServletException {\r\n        \r\n        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, \"Unauthorized\");\r\n  }\r\n}<\/pre>\n<\/div>\n<p>Filter<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">package jp.kd2.jwttest.util;\r\n\r\nimport java.io.IOException;\r\nimport javax.servlet.FilterChain;\r\nimport javax.servlet.ServletException;\r\nimport javax.servlet.http.HttpServletRequest;\r\nimport javax.servlet.http.HttpServletResponse;\r\n\r\nimport org.springframework.beans.factory.annotation.Autowired;\r\nimport org.springframework.security.authentication.UsernamePasswordAuthenticationToken;\r\nimport org.springframework.security.core.context.SecurityContextHolder;\r\nimport org.springframework.security.core.userdetails.UserDetails;\r\nimport org.springframework.security.web.authentication.WebAuthenticationDetailsSource;\r\nimport org.springframework.stereotype.Component;\r\nimport org.springframework.web.filter.OncePerRequestFilter;\r\nimport io.jsonwebtoken.ExpiredJwtException;\r\n\r\nimport jp.kd2.jwttest.service.JwtUserDetailsService;\r\n\r\n@Component\r\npublic class JwtFilter extends OncePerRequestFilter {\r\n    \r\n    @Autowired\r\n    private JwtUserDetailsService userDetailsService;\r\n   \r\n    @Autowired\r\n    private JwtTokenManager tokenManager;\r\n   \r\n    @Override\r\n    protected void doFilterInternal(\r\n            HttpServletRequest request,\r\n            HttpServletResponse response, \r\n            FilterChain filterChain)\r\n                throws ServletException, IOException {\r\n      \r\n        String tokenHeader = request.getHeader(\"Authorization\");\r\n        String username = null;\r\n        String token = null;\r\n        if (tokenHeader != null &amp;&amp; tokenHeader.startsWith(\"Bearer \")) {\r\n            token = tokenHeader.substring(7);\r\n            \r\n            try {\r\n                username = tokenManager.getUsernameFromToken(token);\r\n            } catch (IllegalArgumentException e) {\r\n                System.out.println(\"Unable to get JWT Token\");\r\n            } catch (ExpiredJwtException e) {\r\n                System.out.println(\"JWT Token has expired\");\r\n            }\r\n        } else {\r\n            System.out.println(\"Bearer String was not found in token\");\r\n        }\r\n        \r\n        if (username != null &amp;&amp; SecurityContextHolder.getContext().getAuthentication() == null) {\r\n            UserDetails userDetails = userDetailsService.loadUserByUsername(username);\r\n            if (tokenManager.validateJwtToken(token, userDetails)) {\r\n                UsernamePasswordAuthenticationToken authenticationToken = \r\n                        new UsernamePasswordAuthenticationToken(\r\n                                userDetails, null, userDetails.getAuthorities());\r\n                authenticationToken.setDetails(\r\n                        new WebAuthenticationDetailsSource().buildDetails(request));\r\n                SecurityContextHolder.getContext().setAuthentication(authenticationToken);\r\n            }\r\n        }\r\n        filterChain.doFilter(request, response);\r\n    }\r\n}<\/pre>\n<\/div>\n<p>TokenManager<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">package jp.kd2.jwttest.util;\r\n\r\nimport java.io.Serializable;\r\nimport java.util.Date;\r\nimport java.util.HashMap;\r\nimport java.util.Map;\r\n\r\nimport org.springframework.beans.factory.annotation.Value;\r\nimport org.springframework.security.core.userdetails.UserDetails;\r\nimport org.springframework.stereotype.Component;\r\n\r\nimport io.jsonwebtoken.Claims;\r\nimport io.jsonwebtoken.Jwts;\r\nimport io.jsonwebtoken.SignatureAlgorithm; \r\n\r\n@Component \r\npublic class JwtTokenManager implements Serializable {\r\n\r\n    private static final long serialVersionUID = 1L; \r\n    \r\n    public static final long TOKEN_VALIDITY = 600; \/\/ 600sec = 10mins\r\n    \r\n    @Value(\"${secret}\") \r\n    private String jwtSecret; \r\n   \r\n    public String generateJwtToken(UserDetails userDetails) { \r\n        Map&lt;String, Object&gt; claims = new HashMap&lt;&gt;(); \r\n        \r\n        return Jwts.builder().setClaims(claims).setSubject(userDetails.getUsername())\r\n                .setIssuedAt(new Date(System.currentTimeMillis()))\r\n                .setExpiration(new Date(System.currentTimeMillis() + TOKEN_VALIDITY * 1000))\r\n                .signWith(SignatureAlgorithm.HS512, jwtSecret).compact(); \r\n    }\r\n    \r\n    public Boolean validateJwtToken(String token, UserDetails userDetails) { \r\n        String username = getUsernameFromToken(token); \r\n        Claims claims = Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody();\r\n        Boolean isTokenExpired = claims.getExpiration().before(new Date()); \r\n        return (username.equals(userDetails.getUsername()) &amp;&amp; !isTokenExpired); \r\n    }\r\n    \r\n    public String getUsernameFromToken(String token) {\r\n        final Claims claims = Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody(); \r\n        return claims.getSubject(); \r\n    } \r\n}<\/pre>\n<\/div>\n<p>JUnit\u3067\u30c6\u30b9\u30c8\u3059\u308b\u30af\u30e9\u30b9\u3002<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">package jp.kd2.jwttest;\r\n\r\nimport static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;\r\nimport static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;\r\nimport static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;\r\n\r\nimport org.junit.jupiter.api.Test;\r\nimport org.junit.runner.RunWith;\r\nimport org.springframework.beans.factory.annotation.Autowired;\r\nimport org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;\r\nimport org.springframework.boot.test.context.SpringBootTest;\r\nimport org.springframework.test.context.junit4.SpringRunner;\r\nimport org.springframework.test.web.servlet.MockMvc;\r\n\r\n\/**\r\n * \u30c6\u30b9\u30c8\u30af\u30e9\u30b9\r\n *\/\r\n@RunWith(SpringRunner.class)\r\n@SpringBootTest\r\n@AutoConfigureMockMvc\r\npublic class JwtAuthenticationTest {\r\n\r\n    @Autowired\r\n    private MockMvc mockMvc;\r\n    \r\n    @Test\r\n    public void testJwtAuthentication() throws Exception {\r\n        \r\n        \/\/ \u6b63\u3057\u3044\u30e6\u30fc\u30b6\/\u30d1\u30b9\u30ef\u30fc\u30c9 : 200\u304c\u8fd4\u308b\u3002\r\n        this.mockMvc.perform(post(\"\/login\")\r\n            .content(\"{ \\\"username\\\":\\\"jwtuser\\\", \\\"password\\\":\\\"password\\\" }\")\r\n            .contentType(\"application\/json\"))\r\n            .andDo(print()).andExpect(status().isOk());\r\n        \/\/ \u9593\u9055\u3063\u305f\u30d1\u30b9\u30ef\u30fc\u30c9 : 401\u304c\u8fd4\u308b\u3002\r\n        this.mockMvc.perform(post(\"\/login\")\r\n            .content(\"{ \\\"username\\\":\\\"jwtuser\\\", \\\"password\\\":\\\"wrongpassword\\\" }\")\r\n            .contentType(\"application\/json\"))\r\n            .andDo(print()).andExpect(status().is4xxClientError());\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u78ba\u8a8d\u3059\u308b\u30af\u30e9\u30b9\u3002<\/p>\n<div class=\"wp-block-codemirror-blocks code-block \">\n<pre class=\"CodeMirror\" data-setting=\"{&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-java&quot;,&quot;theme&quot;:&quot;eclipse&quot;,&quot;lineNumbers&quot;:true,&quot;lineWrapping&quot;:false,&quot;styleActiveLine&quot;:false,&quot;readOnly&quot;:true,&quot;align&quot;:&quot;&quot;}\">package jp.kd2.jwttest;\r\n\r\nimport org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;\r\n\r\npublic class PasswordTest {\r\n\r\n    public static void main(String[] args) {\r\n        \/\/ \u540c\u3058\u30d1\u30b9\u30ef\u30fc\u30c9\u3067\u3082\u6bce\u56de\u9055\u3046\u5024\u304c\u8fd4\u308b\u3053\u3068\u3092\u78ba\u8a8d\u3059\u308b\u3002\r\n        for (int i = 0; i &lt; 100; i++) {\r\n            String password = \"password\";\r\n            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();\r\n            String encrypted = passwordEncoder.encode(password);\r\n            System.out.println(encrypted);    \r\n        }\r\n    }\r\n}\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>RFC7519 : JWT pom.xml &lt;dependency&gt; &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt; &lt;artifactI&hellip; <a class=\"more-link\" href=\"https:\/\/www.kd2.jp\/memo3\/?p=325\">\u7d9a\u304d\u3092\u8aad\u3080 <span class=\"screen-reader-text\">Spring + RESTful + JWT<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[16],"tags":[],"_links":{"self":[{"href":"https:\/\/www.kd2.jp\/memo3\/index.php?rest_route=\/wp\/v2\/posts\/325"}],"collection":[{"href":"https:\/\/www.kd2.jp\/memo3\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kd2.jp\/memo3\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kd2.jp\/memo3\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kd2.jp\/memo3\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=325"}],"version-history":[{"count":16,"href":"https:\/\/www.kd2.jp\/memo3\/index.php?rest_route=\/wp\/v2\/posts\/325\/revisions"}],"predecessor-version":[{"id":364,"href":"https:\/\/www.kd2.jp\/memo3\/index.php?rest_route=\/wp\/v2\/posts\/325\/revisions\/364"}],"wp:attachment":[{"href":"https:\/\/www.kd2.jp\/memo3\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=325"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kd2.jp\/memo3\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=325"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kd2.jp\/memo3\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=325"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}