目录
- 1. JWT的结构
- 2. JWT的优点
- 3. JWT的流转过程
- 4.具体案例
- 一、项目结构
- 二、依赖配置
- 三、用户模型
- 四、JWT工具类
- 五、JWT请求过滤器
- 六、安全配置
- 七、身份验证控制器
- 八、测试JWT
JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用环境间以紧凑的方式安全地传递信息。JWT可以被用作身份验证和信息交换的手段,特别适合用于前后端分离的应用程序。
1. JWT的结构
JWT由三部分组成:
-
Header(头部): 通常包含令牌的类型(JWT)和所使用的签名算法(如HMAC SHA256或RSA)。
-
Payload(负载): 包含声明(claims),即要传递的数据。其中可以包含注册声明(如 iss、exp、sub 等)和自定义声明。
-
Signature(签名): 用于验证消息的完整性和发送者的身份。通过将编码后的header和payload与一个密钥结合,利用指定的算法生成。
JWT的格式如下:
java">token class-name">token namespace">eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9token punctuation">.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQtoken punctuation">.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
2. JWT的优点
- 无状态: 不需要在服务器存储会话信息,减轻了服务器的负担。
- 跨域: 可以在不同的域之间进行身份验证。
- 自包含: 含有用户身份信息,避免频繁查询数据库。
3. JWT的流转过程
- 用户通过登录接口发送用户名和密码。
- 服务器验证用户信息,如果成功,则生成JWT并返回给用户。
- 用户在后续请求中带上JWT,通常放在HTTP请求的Authorization头中。
- 服务器解析JWT,验证其有效性,允许或拒绝请求。
4.具体案例
好的,让我们更详细地探讨如何在Java Spring Boot应用程序中实现JWT身份验证,包括每一步的代码和说明。
一、项目结构
Spring Boot项目结构如下:
src
├── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── jwt
│ │ ├── JwtApplication.java
│ │ ├── config
│ │ │ └── SecurityConfig.java
│ │ ├── controller
│ │ │ └── AuthController.java
│ │ ├── model
│ │ │ └── User.java
│ │ ├── service
│ │ │ └── JwtUtil.java
│ │ └── filter
│ │ └── JwtRequestFilter.java
│ └── resources
│ └── application.properties
└── test
二、依赖配置
在pom.xml
中添加必要的依赖:
token tag">token tag">token punctuation"><dependenciestoken punctuation">>token tag">token tag">token punctuation"><dependencytoken punctuation">>token tag">token tag">token punctuation"><groupIdtoken punctuation">>org.springframework.boottoken tag">token tag">token punctuation"></groupIdtoken punctuation">>token tag">token tag">token punctuation"><artifactIdtoken punctuation">>spring-boot-starter-webtoken tag">token tag">token punctuation"></artifactIdtoken punctuation">>token tag">token tag">token punctuation"></dependencytoken punctuation">>token tag">token tag">token punctuation"><dependencytoken punctuation">>token tag">token tag">token punctuation"><groupIdtoken punctuation">>org.springframework.boottoken tag">token tag">token punctuation"></groupIdtoken punctuation">>token tag">token tag">token punctuation"><artifactIdtoken punctuation">>spring-boot-starter-securitytoken tag">token tag">token punctuation"></artifactIdtoken punctuation">>token tag">token tag">token punctuation"></dependencytoken punctuation">>token tag">token tag">token punctuation"><dependencytoken punctuation">>token tag">token tag">token punctuation"><groupIdtoken punctuation">>io.jsonwebtokentoken tag">token tag">token punctuation"></groupIdtoken punctuation">>token tag">token tag">token punctuation"><artifactIdtoken punctuation">>jjwttoken tag">token tag">token punctuation"></artifactIdtoken punctuation">>token tag">token tag">token punctuation"><versiontoken punctuation">>0.9.1token tag">token tag">token punctuation"></versiontoken punctuation">>token tag">token tag">token punctuation"></dependencytoken punctuation">>
token tag">token tag">token punctuation"></dependenciestoken punctuation">>
三、用户模型
创建一个简单的用户模型:
java">token keyword">package token namespace">comtoken punctuation">.exampletoken punctuation">.jwttoken punctuation">.modeltoken punctuation">;token keyword">public token keyword">class token class-name">User token punctuation">{token keyword">private token class-name">String usernametoken punctuation">;token keyword">private token class-name">String passwordtoken punctuation">;token comment">// Constructors, getters, and setterstoken comment">//也可以使用Lomboktoken keyword">public token class-name">Usertoken punctuation">(token class-name">String usernametoken punctuation">, token class-name">String passwordtoken punctuation">) token punctuation">{token keyword">thistoken punctuation">.username token operator">= usernametoken punctuation">;token keyword">thistoken punctuation">.password token operator">= passwordtoken punctuation">;token punctuation">}token keyword">public token class-name">String token function">getUsernametoken punctuation">(token punctuation">) token punctuation">{token keyword">return usernametoken punctuation">;token punctuation">}token keyword">public token class-name">String token function">getPasswordtoken punctuation">(token punctuation">) token punctuation">{token keyword">return passwordtoken punctuation">;token punctuation">}
token punctuation">}
四、JWT工具类
创建JWT工具类,负责生成和解析JWT:
java">token keyword">package token namespace">comtoken punctuation">.exampletoken punctuation">.jwttoken punctuation">.servicetoken punctuation">;token keyword">import token namespace">iotoken punctuation">.jsonwebtokentoken punctuation">.token class-name">Claimstoken punctuation">;
token keyword">import token namespace">iotoken punctuation">.jsonwebtokentoken punctuation">.token class-name">Jwtstoken punctuation">;
token keyword">import token namespace">iotoken punctuation">.jsonwebtokentoken punctuation">.token class-name">SignatureAlgorithmtoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.stereotypetoken punctuation">.token class-name">Componenttoken punctuation">;token keyword">import token namespace">javatoken punctuation">.utiltoken punctuation">.token class-name">Datetoken punctuation">;
token keyword">import token namespace">javatoken punctuation">.utiltoken punctuation">.token class-name">HashMaptoken punctuation">;
token keyword">import token namespace">javatoken punctuation">.utiltoken punctuation">.token class-name">Maptoken punctuation">;
token comment">/**
*Jwt工具类
*/
token annotation punctuation">@Componenttoken comment">//加入Spring容器
token keyword">public token keyword">class token class-name">JwtUtil token punctuation">{token keyword">private token class-name">String secret token operator">= token string">"your_secret_key"token punctuation">; token comment">// 强密码token keyword">private token keyword">long expiration token operator">= token number">60 token operator">* token number">60 token operator">* token number">1000token punctuation">; token comment">// 1小时token comment">//这个方法用于生成 JWT。它接受用户名作为参数。token keyword">public token class-name">String token function">generateTokentoken punctuation">(token class-name">String usernametoken punctuation">) token punctuation">{token class-name">Maptoken generics">token punctuation"><token class-name">Stringtoken punctuation">, token class-name">Objecttoken punctuation">> claims token operator">= token keyword">new token class-name">HashMaptoken generics">token punctuation"><token punctuation">>token punctuation">(token punctuation">)token punctuation">;token keyword">return token function">createTokentoken punctuation">(claimstoken punctuation">, usernametoken punctuation">)token punctuation">;token punctuation">}token comment">//私有方法,用于实际生成 JWTtoken keyword">private token class-name">String token function">createTokentoken punctuation">(token class-name">Maptoken generics">token punctuation"><token class-name">Stringtoken punctuation">, token class-name">Objecttoken punctuation">> claimstoken punctuation">, token class-name">String subjecttoken punctuation">) token punctuation">{token keyword">return token class-name">Jwtstoken punctuation">.token function">buildertoken punctuation">(token punctuation">)token comment">//开始构建 JWT 的构建器token punctuation">.token function">setClaimstoken punctuation">(claimstoken punctuation">)token comment">//设置 JWT 中的声明token punctuation">.token function">setSubjecttoken punctuation">(subjecttoken punctuation">)token comment">//设置主题(通常是用户名)token punctuation">.token function">setIssuedAttoken punctuation">(token keyword">new token class-name">Datetoken punctuation">(token class-name">Systemtoken punctuation">.token function">currentTimeMillistoken punctuation">(token punctuation">)token punctuation">)token punctuation">)token comment">//设置 JWT 的签发时间token punctuation">.token function">setExpirationtoken punctuation">(token keyword">new token class-name">Datetoken punctuation">(token class-name">Systemtoken punctuation">.token function">currentTimeMillistoken punctuation">(token punctuation">) token operator">+ expirationtoken punctuation">)token punctuation">)token comment">//设置 JWT 的过期时间token punctuation">.token function">signWithtoken punctuation">(token class-name">SignatureAlgorithmtoken punctuation">.HS256token punctuation">, secrettoken punctuation">)token comment">//使用指定的算法(HS256)和密钥对 JWT 进行签名token punctuation">.token function">compacttoken punctuation">(token punctuation">)token punctuation">;token comment">//生成最终的 JWT 字符串token punctuation">}token comment">//用于验证给定的 JWT 是否有效。token keyword">public token class-name">Boolean token function">validateTokentoken punctuation">(token class-name">String tokentoken punctuation">, token class-name">String usernametoken punctuation">) token punctuation">{token keyword">final token class-name">String extractedUsername token operator">= token function">extractUsernametoken punctuation">(tokentoken punctuation">)token punctuation">;token comment">//提取 JWT 中的用户名token keyword">return token punctuation">(extractedUsernametoken punctuation">.token function">equalstoken punctuation">(usernametoken punctuation">) token operator">&& token operator">!token function">isTokenExpiredtoken punctuation">(tokentoken punctuation">)token punctuation">)token punctuation">;token comment">//检查提取的用户名与提供的用户名是否匹配,并且检查 JWT 是否未过期token punctuation">}token comment">//从 JWT 中提取用户名token keyword">public token class-name">String token function">extractUsernametoken punctuation">(token class-name">String tokentoken punctuation">) token punctuation">{token keyword">return token function">extractAllClaimstoken punctuation">(tokentoken punctuation">)token punctuation">.token function">getSubjecttoken punctuation">(token punctuation">)token punctuation">;token punctuation">}token comment">//解析 JWT 并返回所有声明token keyword">private token class-name">Claims token function">extractAllClaimstoken punctuation">(token class-name">String tokentoken punctuation">) token punctuation">{token keyword">return token class-name">Jwtstoken punctuation">.token function">parsertoken punctuation">(token punctuation">)token punctuation">.token function">setSigningKeytoken punctuation">(secrettoken punctuation">)token punctuation">.token function">parseClaimsJwstoken punctuation">(tokentoken punctuation">)token punctuation">.token function">getBodytoken punctuation">(token punctuation">)token punctuation">;token punctuation">}token comment">//使用密钥解析 JWT 获取其主体部分(声明)token comment">//检查 JWT 是否已过期token keyword">private token class-name">Boolean token function">isTokenExpiredtoken punctuation">(token class-name">String tokentoken punctuation">) token punctuation">{token keyword">return token function">extractAllClaimstoken punctuation">(tokentoken punctuation">)token punctuation">.token function">getExpirationtoken punctuation">(token punctuation">)token punctuation">.token function">beforetoken punctuation">(token keyword">new token class-name">Datetoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token punctuation">}
token punctuation">}
五、JWT请求过滤器
创建JWT请求过滤器,用于拦截请求并验证JWT:
java">token keyword">package token namespace">comtoken punctuation">.exampletoken punctuation">.jwttoken punctuation">.filtertoken punctuation">;token keyword">import token namespace">comtoken punctuation">.exampletoken punctuation">.jwttoken punctuation">.servicetoken punctuation">.token class-name">JwtUtiltoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.beanstoken punctuation">.factorytoken punctuation">.annotationtoken punctuation">.token class-name">Autowiredtoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.coretoken punctuation">.contexttoken punctuation">.token class-name">SecurityContextHoldertoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.coretoken punctuation">.userdetailstoken punctuation">.token class-name">UserDetailstoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.coretoken punctuation">.userdetailstoken punctuation">.token class-name">UserDetailsServicetoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.webtoken punctuation">.authenticationtoken punctuation">.token class-name">WebAuthenticationDetailsSourcetoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.stereotypetoken punctuation">.token class-name">Componenttoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.webtoken punctuation">.filtertoken punctuation">.token class-name">OncePerRequestFiltertoken punctuation">;token keyword">import token namespace">javaxtoken punctuation">.servlettoken punctuation">.token class-name">FilterChaintoken punctuation">;
token keyword">import token namespace">javaxtoken punctuation">.servlettoken punctuation">.token class-name">ServletExceptiontoken punctuation">;
token keyword">import token namespace">javaxtoken punctuation">.servlettoken punctuation">.httptoken punctuation">.token class-name">HttpServletRequesttoken punctuation">;
token keyword">import token namespace">javaxtoken punctuation">.servlettoken punctuation">.httptoken punctuation">.token class-name">HttpServletResponsetoken punctuation">;
token keyword">import token namespace">javatoken punctuation">.iotoken punctuation">.token class-name">IOExceptiontoken punctuation">;token annotation punctuation">@Component token comment">// 将该类标记为 Spring 组件,以便自动扫描和管理
token keyword">public token keyword">class token class-name">JwtRequestFilter token keyword">extends token class-name">OncePerRequestFilter token punctuation">{token annotation punctuation">@Autowired token comment">// 自动注入 JwtUtil 实例token keyword">private token class-name">JwtUtil jwtUtiltoken punctuation">;token annotation punctuation">@Autowired token comment">// 自动注入 UserDetailsService 实例token keyword">private token class-name">UserDetailsService userDetailsServicetoken punctuation">;token annotation punctuation">@Overridetoken keyword">protected token keyword">void token function">doFilterInternaltoken punctuation">(token class-name">HttpServletRequest requesttoken punctuation">, token class-name">HttpServletResponse responsetoken punctuation">, token class-name">FilterChain chaintoken punctuation">)token keyword">throws token class-name">ServletExceptiontoken punctuation">, token class-name">IOException token punctuation">{token comment">// 从请求中获取 Authorization 头部token keyword">final token class-name">String authorizationHeader token operator">= requesttoken punctuation">.token function">getHeadertoken punctuation">(token string">"Authorization"token punctuation">)token punctuation">;token class-name">String username token operator">= token keyword">nulltoken punctuation">; token comment">// 初始化用户名token class-name">String jwt token operator">= token keyword">nulltoken punctuation">; token comment">// 初始化 JWT 令牌token comment">// 检查 Authorization 头部是否存在且以 "Bearer " 开头token keyword">if token punctuation">(authorizationHeader token operator">!= token keyword">null token operator">&& authorizationHeadertoken punctuation">.token function">startsWithtoken punctuation">(token string">"Bearer "token punctuation">)token punctuation">) token punctuation">{token comment">// 提取 JWT 令牌(去掉 "Bearer " 前缀)jwt token operator">= authorizationHeadertoken punctuation">.token function">substringtoken punctuation">(token number">7token punctuation">)token punctuation">;token comment">// 从 JWT 中提取用户名username token operator">= jwtUtiltoken punctuation">.token function">extractUsernametoken punctuation">(jwttoken punctuation">)token punctuation">;token punctuation">}token comment">// 如果用户名不为空且当前 SecurityContext 没有身份验证信息token keyword">if token punctuation">(username token operator">!= token keyword">null token operator">&& token class-name">SecurityContextHoldertoken punctuation">.token function">getContexttoken punctuation">(token punctuation">)token punctuation">.token function">getAuthenticationtoken punctuation">(token punctuation">) token operator">== token keyword">nulltoken punctuation">) token punctuation">{token comment">// 根据用户名加载用户详细信息token class-name">UserDetails userDetails token operator">= userDetailsServicetoken punctuation">.token function">loadUserByUsernametoken punctuation">(usernametoken punctuation">)token punctuation">;token comment">// 验证 JWT 是否有效token keyword">if token punctuation">(jwtUtiltoken punctuation">.token function">validateTokentoken punctuation">(jwttoken punctuation">, userDetailstoken punctuation">.token function">getUsernametoken punctuation">(token punctuation">)token punctuation">)token punctuation">) token punctuation">{token comment">// 创建身份验证令牌,并设置用户的权限token class-name">UsernamePasswordAuthenticationToken authenticationToken token operator">=token keyword">new token class-name">UsernamePasswordAuthenticationTokentoken punctuation">(userDetailstoken punctuation">, token keyword">nulltoken punctuation">, userDetailstoken punctuation">.token function">getAuthoritiestoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token comment">// 设置请求的详细信息authenticationTokentoken punctuation">.token function">setDetailstoken punctuation">(token keyword">new token class-name">WebAuthenticationDetailsSourcetoken punctuation">(token punctuation">)token punctuation">.token function">buildDetailstoken punctuation">(requesttoken punctuation">)token punctuation">)token punctuation">;token comment">// 将身份验证信息存入 SecurityContexttoken class-name">SecurityContextHoldertoken punctuation">.token function">getContexttoken punctuation">(token punctuation">)token punctuation">.token function">setAuthenticationtoken punctuation">(authenticationTokentoken punctuation">)token punctuation">;token punctuation">}token punctuation">}token comment">// 继续过滤器链chaintoken punctuation">.token function">doFiltertoken punctuation">(requesttoken punctuation">, responsetoken punctuation">)token punctuation">;token punctuation">}
token punctuation">}
六、安全配置
配置Spring Security,以保护API并使用JWT:
java">token keyword">package token namespace">comtoken punctuation">.exampletoken punctuation">.jwttoken punctuation">.configtoken punctuation">;token keyword">import token namespace">comtoken punctuation">.exampletoken punctuation">.jwttoken punctuation">.filtertoken punctuation">.token class-name">JwtRequestFiltertoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.beanstoken punctuation">.factorytoken punctuation">.annotationtoken punctuation">.token class-name">Autowiredtoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.contexttoken punctuation">.annotationtoken punctuation">.token class-name">Beantoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.contexttoken punctuation">.annotationtoken punctuation">.token class-name">Configurationtoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.authenticationtoken punctuation">.token class-name">AuthenticationManagertoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.configtoken punctuation">.annotationtoken punctuation">.authenticationtoken punctuation">.builderstoken punctuation">.token class-name">AuthenticationManagerBuildertoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.configtoken punctuation">.annotationtoken punctuation">.webtoken punctuation">.builderstoken punctuation">.token class-name">HttpSecuritytoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.configtoken punctuation">.annotationtoken punctuation">.webtoken punctuation">.configurationtoken punctuation">.token class-name">EnableWebSecuritytoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.configtoken punctuation">.annotationtoken punctuation">.webtoken punctuation">.configurationtoken punctuation">.token class-name">WebSecurityConfigurerAdaptertoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.configtoken punctuation">.httptoken punctuation">.token class-name">SessionCreationPolicytoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.cryptotoken punctuation">.bcrypttoken punctuation">.token class-name">BCryptPasswordEncodertoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.cryptotoken punctuation">.passwordtoken punctuation">.token class-name">PasswordEncodertoken punctuation">;token annotation punctuation">@Configuration
token annotation punctuation">@EnableWebSecurity
token keyword">public token keyword">class token class-name">SecurityConfig token keyword">extends token class-name">WebSecurityConfigurerAdapter token punctuation">{token annotation punctuation">@Autowiredtoken keyword">private token class-name">JwtRequestFilter jwtRequestFiltertoken punctuation">;token annotation punctuation">@Overridetoken keyword">protected token keyword">void token function">configuretoken punctuation">(token class-name">HttpSecurity httptoken punctuation">) token keyword">throws token class-name">Exception token punctuation">{httptoken punctuation">.token function">csrftoken punctuation">(token punctuation">)token punctuation">.token function">disabletoken punctuation">(token punctuation">)token punctuation">.token function">authorizeRequeststoken punctuation">(token punctuation">)token punctuation">.token function">antMatcherstoken punctuation">(token string">"/auth/login"token punctuation">)token punctuation">.token function">permitAlltoken punctuation">(token punctuation">) token comment">// 公开登录接口token punctuation">.token function">anyRequesttoken punctuation">(token punctuation">)token punctuation">.token function">authenticatedtoken punctuation">(token punctuation">) token comment">// 其他接口需要认证token punctuation">.token function">andtoken punctuation">(token punctuation">)token punctuation">.token function">sessionManagementtoken punctuation">(token punctuation">)token punctuation">.token function">sessionCreationPolicytoken punctuation">(token class-name">SessionCreationPolicytoken punctuation">.STATELESStoken punctuation">)token punctuation">; token comment">// 无状态会话token comment">// 添加JWT过滤器httptoken punctuation">.token function">addFilterBeforetoken punctuation">(jwtRequestFiltertoken punctuation">, token class-name">UsernamePasswordAuthenticationFiltertoken punctuation">.token keyword">classtoken punctuation">)token punctuation">;token punctuation">}token annotation punctuation">@Overridetoken keyword">protected token keyword">void token function">configuretoken punctuation">(token class-name">AuthenticationManagerBuilder authtoken punctuation">) token keyword">throws token class-name">Exception token punctuation">{authtoken punctuation">.token function">inMemoryAuthenticationtoken punctuation">(token punctuation">)token punctuation">.token function">withUsertoken punctuation">(token string">"user"token punctuation">)token punctuation">.token function">passwordtoken punctuation">(token function">passwordEncodertoken punctuation">(token punctuation">)token punctuation">.token function">encodetoken punctuation">(token string">"password"token punctuation">)token punctuation">)token punctuation">.token function">rolestoken punctuation">(token string">"USER"token punctuation">)token punctuation">; token comment">// 示例用户token punctuation">}token annotation punctuation">@Beantoken keyword">public token class-name">PasswordEncoder token function">passwordEncodertoken punctuation">(token punctuation">) token punctuation">{token keyword">return token keyword">new token class-name">BCryptPasswordEncodertoken punctuation">(token punctuation">)token punctuation">;token punctuation">}token annotation punctuation">@Beantoken annotation punctuation">@Overridetoken keyword">public token class-name">AuthenticationManager token function">authenticationManagerBeantoken punctuation">(token punctuation">) token keyword">throws token class-name">Exception token punctuation">{token keyword">return token keyword">supertoken punctuation">.token function">authenticationManagerBeantoken punctuation">(token punctuation">)token punctuation">;token punctuation">}
token punctuation">}
七、身份验证控制器
创建一个控制器来处理登录请求并返回JWT:
java">token keyword">package token namespace">comtoken punctuation">.exampletoken punctuation">.jwttoken punctuation">.controllertoken punctuation">;token keyword">import token namespace">comtoken punctuation">.exampletoken punctuation">.jwttoken punctuation">.modeltoken punctuation">.token class-name">Usertoken punctuation">;
token keyword">import token namespace">comtoken punctuation">.exampletoken punctuation">.jwttoken punctuation">.servicetoken punctuation">.token class-name">JwtUtiltoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.beanstoken punctuation">.factorytoken punctuation">.annotationtoken punctuation">.token class-name">Autowiredtoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.authenticationtoken punctuation">.token class-name">AuthenticationManagertoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.authenticationtoken punctuation">.token class-name">UsernamePasswordAuthenticationTokentoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.coretoken punctuation">.userdetailstoken punctuation">.token class-name">UserDetailstoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.securitytoken punctuation">.coretoken punctuation">.userdetailstoken punctuation">.token class-name">UserDetailsServicetoken punctuation">;
token keyword">import token namespace">orgtoken punctuation">.springframeworktoken punctuation">.webtoken punctuation">.bindtoken punctuation">.annotationtoken punctuation">.token operator">*token punctuation">;token annotation punctuation">@RestController
token annotation punctuation">@RequestMappingtoken punctuation">(token string">"/auth"token punctuation">)
token keyword">public token keyword">class token class-name">AuthController token punctuation">{token annotation punctuation">@Autowiredtoken keyword">private token class-name">JwtUtil jwtUtiltoken punctuation">;token annotation punctuation">@Autowiredtoken keyword">private token class-name">AuthenticationManager authenticationManagertoken punctuation">;token annotation punctuation">@Autowiredtoken keyword">private token class-name">UserDetailsService userDetailsServicetoken punctuation">;token annotation punctuation">@PostMappingtoken punctuation">(token string">"/login"token punctuation">)token keyword">public token class-name">String token function">logintoken punctuation">(token annotation punctuation">@RequestBody token class-name">User usertoken punctuation">) token punctuation">{token keyword">try token punctuation">{authenticationManagertoken punctuation">.token function">authenticatetoken punctuation">(token keyword">new token class-name">UsernamePasswordAuthenticationTokentoken punctuation">(usertoken punctuation">.token function">getUsernametoken punctuation">(token punctuation">)token punctuation">, usertoken punctuation">.token function">getPasswordtoken punctuation">(token punctuation">)token punctuation">)token punctuation">)token punctuation">;token punctuation">} token keyword">catch token punctuation">(token class-name">Exception etoken punctuation">) token punctuation">{token keyword">throw token keyword">new token class-name">RuntimeExceptiontoken punctuation">(token string">"Invalid credentials"token punctuation">)token punctuation">;token punctuation">}token keyword">final token class-name">UserDetails userDetails token operator">= userDetailsServicetoken punctuation">.token function">loadUserByUsernametoken punctuation">(usertoken punctuation">.token function">getUsernametoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token keyword">return jwtUtiltoken punctuation">.token function">generateTokentoken punctuation">(userDetailstoken punctuation">.token function">getUsernametoken punctuation">(token punctuation">)token punctuation">)token punctuation">;token punctuation">}
token punctuation">}
八、测试JWT
- 启动Spring Boot应用程序。
- 使用Postman或其他工具测试登录接口。
请求示例:
POST /auth/login
Content-Type: application/json{"username": "user","password": "password"
}
响应示例:
{"token": "eyJhbGciOiJIUzI1NiIsInR5c..."
}
- 使用返回的token访问受保护的资源:
GET /protected/resource
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5c...