- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我将 spring boot 和 spring security 与 JWT on rest 服务一起使用。我使用了以下链接中的代码: https://www.javainuse.com/spring/boot-jwt-mysql它工作正常但是当我们使用它的 token 进行身份验证时......我们面临以下错误:
io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:354) ~[jjwt-0.9.1.jar:0.9.1]
at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:481) ~[jjwt-0.9.1.jar:0.9.1]
at io.jsonwebtoken.impl.DefaultJwtParser.parseClaimsJws(DefaultJwtParser.java:541) ~[jjwt-0.9.1.jar:0.9.1]
at com.isan.config.JwtTokenUtil.getAllClaimsFromToken(JwtTokenUtil.java:46) ~[classes/:na]
at com.isan.config.JwtTokenUtil.getClaimFromToken(JwtTokenUtil.java:41) ~[classes/:na]
at com.isan.config.JwtTokenUtil.getUsernameFromToken(JwtTokenUtil.java:32) ~[classes/:na]
at com.isan.config.JwtRequestFilter.doFilterInternal(JwtRequestFilter.java:44) ~[classes/:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.1.jar:5.3.1]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:336) ~[spring-security-web-5.4.1.jar:5.4.1]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:103) ~[spring-security-web-5.4.1.jar:5.4.1]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:89) ~[spring-security-web-5.4.1.jar:5.4.1]
这些是代码:
1-WebSecurityConfig类:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
private UserDetailsService jwtUserDetailsService;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// configure AuthenticationManager so that it knows from where to load
// user for matching credentials
// Use BCryptPasswordEncoder
auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
// We don't need CSRF for this example
httpSecurity.csrf().disable()
// dont authenticate this particular request
.authorizeRequests().antMatchers("/authenticate", "/register").permitAll().
// all other requests need to be authenticated
anyRequest().authenticated().and().
// make sure we use stateless session; session won't be used to
// store user's state.
exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Add a filter to validate the tokens with every request
httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
}
2-JwtTokenUtil类:
@Component
public class JwtTokenUtil implements Serializable {
private static final long serialVersionUID = -2550185165626007488L;
public static final long JWT_TOKEN_VALIDITY = 5 * 60 * 60;
@Value("${jwt.secret}")
private String secret;
//retrieve username from jwt token
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
//retrieve expiration date from jwt token
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
//for retrieveing any information from token we will need the secret key
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser().setSigningKey(secret.getBytes()).parseClaimsJws(token).getBody();
}
//check if the token has expired
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
//generate token for user
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, userDetails.getUsername());
}
//while creating the token -
//1. Define claims of the token, like Issuer, Expiration, Subject, and the ID
//2. Sign the JWT using the HS512 algorithm and secret key.
//3. According to JWS Compact Serialization(https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#section-3.1)
// compaction of the JWT to a URL-safe string
private String doGenerateToken(Map<String, Object> claims, String subject) {
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000))
.signWith(SignatureAlgorithm.HS512, secret.getBytes()).compact();
}
//validate token
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
}
3-JwtRequestFilter类:
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private JwtUserDetailsService jwtUserDetailsService;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String requestTokenHeader = request.getHeader("Authorization");
String username = null;
String jwtToken = null;
// JWT Token is in the form "Bearer token". Remove Bearer word and get
// only the Token
if (requestTokenHeader != null && requestTokenHeader.startsWith("Bearer ")) {
jwtToken = requestTokenHeader.substring(7);
try {
username = jwtTokenUtil.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
System.out.println("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
System.out.println("JWT Token has expired");
}
} else {
logger.warn("JWT Token does not begin with Bearer String");
}
// Once we get the token validate it.
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);
// if token is valid configure Spring Security to manually set
// authentication
if (jwtTokenUtil.validateToken(jwtToken, userDetails)) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// After setting the Authentication in the context, we specify
// that the current user is authenticated. So it passes the
// Spring Security Configurations successfully.
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
4-JwtAuthenticationEntryPoint类:
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
private static final long serialVersionUID = -7858869558953243875L;
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
5-JwtAuthenticationController类:
@RestController
@CrossOrigin
public class JwtAuthenticationController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private JwtUserDetailsService userDetailsService;
@RequestMapping(value = "/authenticate", method = RequestMethod.POST)
public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtRequest authenticationRequest) throws Exception {
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
final UserDetails userDetails = userDetailsService
.loadUserByUsername(authenticationRequest.getUsername());
final String token = jwtTokenUtil.generateToken(userDetails);
return ResponseEntity.ok(new JwtResponse(token));
}
@RequestMapping(value = "/register", method = RequestMethod.POST)
public ResponseEntity<?> saveUser(@RequestBody UserDTO user) throws Exception {
return ResponseEntity.ok(userDetailsService.save(user));
}
private void authenticate(String username, String password) throws Exception {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException e) {
throw new Exception("USER_DISABLED", e);
} catch (BadCredentialsException e) {
throw new Exception("INVALID_CREDENTIALS", e);
}
}
}
6-JwtUserDetailsService类:
@Service
public class JwtUserDetailsService implements UserDetailsService {
@Autowired
private UserDao userDao;
@Autowired
private PasswordEncoder bcryptEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
DAOUser user = userDao.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("User not found with username: " + username);
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(),
new ArrayList<>());
}
public DAOUser save(UserDTO user) {
DAOUser newUser = new DAOUser();
newUser.setUsername(user.getUsername());
newUser.setPassword(bcryptEncoder.encode(user.getPassword()));
return userDao.save(newUser);
}
}
7- application.properties
jwt.secret=javainuse
spring.datasource.url=jdbc:mysql://localhost/bootdb?createDatabaseIfNotExist=true&autoReconnect=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=asdasdasd
spring.datasource.platform=mysql
spring.jpa.hibernate.ddl-auto=create-drop
8-pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.javainuse</groupId>
<artifactId>spring-boot-jwt</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
</project>
9-token 示例:
eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJzYW0iLCJleHAiOjE2MDgwNjM1NTUsImlhdCI6MTYwODA0NTU1NX0.X77D8mceGbBWRCWUOwhL-5iwpZQqFAITmQqOW_s48vGDkkWdMFg1dm_Gackri8evPVzkF6lt2tXvHCbOlpe86w
10 个 secret 的例子:
javainuse
最佳答案
在 JwtTokenUtil 类中,只需更改以下方法:
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser().setSigningKey(secret.getBytes(Charset.forName("UTF-8"))).parseClaimsJws(token.replace("{", "").replace("}","")).getBody();
}
private String doGenerateToken(Map<String, Object> claims, String subject) {
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000))
.signWith(SignatureAlgorithm.HS512, secret.getBytes(Charset.forName("UTF-8"))).compact();
}
关于spring-boot - io.jsonwebtoken.SignatureException : JWT signature does not match locally computed signature,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65306718/
我正在使用 Vue 构建我的第一个 SPA 项目。 我决定在后端使用 NodeJS,但是,使用 JsonWebToken 构建登录功能让我很头疼。 我写了一些代码来查看 JWT 的工作原理,当我试图查
我有一个用于用户身份验证的应用程序,我遇到了这个问题,我有登录的用户并将 JWT (JsonWebToken) 存储在 cookie 中。我在验证用户后存储了 cookie。接下来,我作为管理员,在该
我是 JWT 世界的新手,我想为我的 React Native 应用程序用户创建一个 authToken。 但是,我不愿意让任何人读取里面的内容(例如 userMail、firstName 或 uni
我正在开发一个全栈项目,用户可以在其中创建帐户、访问他们的个人资料、创建博客、阅读他们的博客、删除他们的博客等。为了执行所有这些任务(注册和登录除外),用户必须待验证。 我已经完成了后端,但我不明白如
我正在使用 nodejs 和 angular cli 制作一个 Web 应用程序我正在使用 JWT 来验证我的登录功能。但是当我处理它时抛出了这个错误 Error: Expected "payload
我目前正在使用 React 开发一个网站,我希望能够让用户登录。现在我的策略是在提交时将表单数据发送到服务器( express ),如果信息与我的数据库中的用户匹配,服务器会发回一个没有敏感信息(只有
我正在尝试编译一个 typescript 文件,它一直从编译器中抛出这个错误:错误 TS2339:类型“string”上不存在属性“payload”|目的'。 “string”类型上不存在属性“pay
我收到了 JWT,并想验证它的签名。它未加密,基于 64 编码并使用 HmacSha256 签名。它是用我知道的 secret 签名的。 我似乎找不到任何关于如何在不使用 https://jwt.io
所以我试图通过在 Scalatra 中使用 JWT 来保护我的 Web 应用程序。目前,我将 Scentry 与用户密码和 RememberMe 策略一起使用,我的目的是将 RememberMe 策略
我正在尝试编译一个 typescript 文件,它一直从编译器中抛出这个错误:错误 TS2339:类型“string”上不存在属性“payload”|目的'。 “string”类型上不存在属性“pay
要使 token 无效,据我所知,存储 token 及其过期日期时间到数据库的最佳方法。要验证它,您只需从数据库中选择它,如果它存在,您就知道它已失效。此外,您可以根据过期日期时间从数据库中删除每个过
我目前正在尝试构建一个基于 token 的简单登录系统。我有一个简单的登录表单,可将凭据发送到服务器。创建 token 也对我有用。 如果用户登录并手动打开用户仪表板链接,服务器将收到获取请求。那
据说当您使用 ssl 时,您可以防止中间人从服务器窃取信息到客户端,反之亦然。在我的例子中,窃取了 jsonwebtoken。我还从其他答案中了解到,ssl 使用私钥和公钥。私钥存储在服务器上,公钥提
我正在为 node.js 使用 jsonwebtoken 包: 像这样创建 token : var token = jwt.sign(user, tokenSecret, {expiresInMinu
我正在尝试使用 node.js 设置用户级身份验证,所以我去执行 npm install -g jsonwebtoken --save。但是,当我使用 require('jsonwebtoken')
我正在尝试按照 guide 中的示例将 token 设置为在一小时内过期。 : jwt.sign({ data: 'foobar' }, 'secret', { expiresIn: 60 * 6
我正在尝试使用 Json Web token (在 article 的帮助下)验证我的 nodejs api,但问题是 token 永远不会过期。 var express = require('exp
我想忽略一些针对 token 身份验证进行检查的 API URL 我想保护 post 和 put 方法,但不想保护这个 url 本地主机:3000/api/events/ router.use(fun
我正在使用 jsonwebtoken在 NodeJs API 应用程序中用于验证我的 API 应用程序中的用户。我设置的流程如下: 1) 用户通过注册 API 注册,并使用以下方式生成访问 token
什么是JWT? JSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,也是目前前后端分离项目中普遍使用的认证技术. 本文介绍如何在Golang Gin Web
我是一名优秀的程序员,十分优秀!