[Java Spring JWT] JWT example
2023-09-14 09:00:46 时间
Provider:
package com.example.ec.security; import com.example.ec.domain.Role; import io.jsonwebtoken.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.stereotype.Component; import java.util.*; import java.util.stream.Collectors; /** * Utility Class for common Java Web Token operations * * Created by Mary Ellen Bowman */ @Component public class JwtProvider{ private final String ROLES_KEY = "roles"; private JwtParser parser; private String secretKey; private long validityInMilliseconds; @Autowired public JwtProvider(@Value("${security.jwt.token.secret-key}") String secretKey, @Value("${security.jwt.token.expiration}")long validityInMilliseconds) { this.secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes()); this.validityInMilliseconds = validityInMilliseconds; } /** * Create JWT string given username and roles. * * @param username * @param roles * @return jwt string */ public String createToken(String username, List<Role> roles) { //Add the username to the payload Claims claims = Jwts.claims().setSubject(username); //Convert roles to Spring Security SimpleGrantedAuthority objects, //Add to Simple Granted Authority objects to claims claims.put(ROLES_KEY, roles.stream().map(role ->new SimpleGrantedAuthority(role.getAuthority())) .filter(Objects::nonNull) .collect(Collectors.toList())); //Build the Token Date now = new Date(); return Jwts.builder() .setClaims(claims) .setIssuedAt(now) .setExpiration(new Date(now.getTime() + validityInMilliseconds)) .signWith(SignatureAlgorithm.HS256, secretKey) .compact(); } /** * Validate the JWT String * * @param token JWT string * @return true if valid, false otherwise */ public boolean isValidToken(String token) { try { Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token); return true; } catch (JwtException | IllegalArgumentException e) { return false; } } /** * Get the username from the token string * * @param token jwt * @return username */ public String getUsername(String token) { return Jwts.parser().setSigningKey(secretKey) .parseClaimsJws(token).getBody().getSubject(); } /** * Get the roles from the token string * * @param token jwt * @return username */ public List<GrantedAuthority> getRoles(String token) { List<Map<String, String>> roleClaims = Jwts.parser().setSigningKey(secretKey) .parseClaimsJws(token).getBody().get(ROLES_KEY, List.class); return roleClaims.stream().map(roleClaim -> new SimpleGrantedAuthority(roleClaim.get("authority"))) .collect(Collectors.toList()); } }
Filter:
package com.example.ec.security; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; import org.springframework.web.filter.GenericFilterBean; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.Optional; /** * Filter for Java Web Token Authentication and Authorization * * Created by Mary Ellen Bowman */ public class JwtTokenFilter extends GenericFilterBean { private static final Logger LOGGER = LoggerFactory.getLogger(JwtTokenFilter.class); private static final String BEARER = "Bearer"; private ExploreCaliUserDetailsService userDetailsService; public JwtTokenFilter(ExploreCaliUserDetailsService userDetailsService) { this.userDetailsService = userDetailsService; } /** * Determine if there is a JWT as part of the HTTP Request Header. * If it is valid then set the current context With the Authentication(user and roles) found in the token * * @param req Servlet Request * @param res Servlet Response * @param filterChain Filter Chain * @throws IOException * @throws ServletException */ @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException { LOGGER.info("Process request to check for a JSON Web Token "); //Check for Authorization:Bearer JWT String headerValue = ((HttpServletRequest)req).getHeader("Authorization"); getBearerToken(headerValue).ifPresent(token-> { //Pull the Username and Roles from the JWT to construct the user details userDetailsService.loadUserByJwtToken(token).ifPresent(userDetails -> { //Add the user details (Permissions) to the Context for just this API invocation SecurityContextHolder.getContext().setAuthentication( new PreAuthenticatedAuthenticationToken(userDetails, "", userDetails.getAuthorities())); }); }); //move on to the next filter in the chains filterChain.doFilter(req, res); } /** * if present, extract the jwt token from the "Bearer <jwt>" header value. * * @param headerVal * @return jwt if present, empty otherwise */ private Optional<String> getBearerToken(String headerVal) { if (headerVal != null && headerVal.startsWith(BEARER)) { return Optional.of(headerVal.replace(BEARER, "").trim()); } return Optional.empty(); } }
Security Config:
package com.example.ec.security; import com.example.ec.repo.RoleRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired RoleRepository roleRepository; @Override protected void configure(HttpSecurity http) throws Exception { // Entry points http.authorizeRequests() .antMatchers("/packages/**").permitAll() .antMatchers("/tours/**").permitAll() .antMatchers("/ratings/**").permitAll() .antMatchers("/users/signin").permitAll() // Disallow everything else.. .anyRequest().authenticated(); // Disable CSRF (cross site request forgery) http.csrf().disable(); // No session will be created or used by spring security http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.addFilterBefore(new JwtTokenFilter(userDetailsService), UsernamePasswordAuthenticationFilter.class); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(12); } }
Usage to the endpoints:
package com.example.ec.web; import com.example.ec.domain.User; import com.example.ec.service.UserService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.HttpServerErrorException; import javax.validation.Valid; import java.util.List; @RestController @RequestMapping("/users") public class UserController { private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class); @Autowired private UserService userService; @PostMapping("/signin") public String login(@RequestBody @Valid LoginDto loginDto) { return userService.signin(loginDto.getUsername(), loginDto.getPassword()).orElseThrow(()-> new HttpServerErrorException(HttpStatus.FORBIDDEN, "Login Failed")); } @PostMapping("/signup") @PreAuthorize("hasRole('ROLE_ADMIN')") @ResponseStatus(HttpStatus.CREATED) public User signup(@RequestBody @Valid LoginDto loginDto){ return userService.signup(loginDto.getUsername(), loginDto.getPassword(), loginDto.getFirstName(), loginDto.getLastName()).orElseThrow(() -> new HttpServerErrorException(HttpStatus.BAD_REQUEST,"User already exists")); } @GetMapping @PreAuthorize("hasRole('ROLE_ADMIN')") public List<User> getAllUsers() { return userService.getAll(); } }
相关文章
- 干货--JMS(java消息服务)整合Spring项目案例
- spring boot 之 错误:SpelEvaluationException: EL1008E: Property or field 'timestamp' cannot be found on object of type 'java.util.HashMap'
- Java实现 LeetCode 657 机器人能否返回原点(暴力大法)
- Java实现 LeetCode 433 最小基因变化
- Java实现 LeetCode 372 超级次方
- Java实现 LeetCode 57 插入区间
- java实现第四届蓝桥杯错误票据
- java实现第五届蓝桥杯扑克序列
- Spring异常解决 java.lang.NullPointerException,配置spring管理hibernate时出错
- [Java Spring JWT] JWT example
- [Java Spring Data] Query method clauses and expressions
- [Java spring] Building a command-line application
- [Java Spring] Profiles
- [Java Sprint] Spring XML Configuration : Constructor Injection Demo
- [Java Spring] @InitBinder
- [Java Spring] Profiles
- Java UDP小结
- Java SSM4——Spring
- 本地启动 SAP Commerce Cloud(Hybris) 产生的五个 Java 进程
- 使用Java程序消费SAP Leonardo的机器学习API
- 使用 SAP BTP 创建一个 Spring Boot Java 应用
- Java面试题 对spring IOC和AOP的理解
- 4问教你搞定java中的ThreadLocal
- Java中如何遍历Map对象的4种方法
- 【Android 安全】DEX 加密 ( Java 工具开发 | 生成 dex 文件 | Java 命令行执行 )
- Java final finally finalize有什么不同
- 每天五个java相关面试题(8)--spring篇
- Java基础(13)-流程控制之循环结构