如何在Spring Security中实现基于JWT的身份验证和授权
我试图在我的Spring启动应用程序中实现基于jwt的身份验证和授权。我遵循了这里写的教程。但是它在我的应用程序中没有做任何事情。它不返回jwt令牌,而是我被验证了,我的请求得到了满足。我是Spring安全新手。这是我的代码。
我希望我的应用程序返回jwt令牌,并且使用该令牌必须授权请求。
这是我的密码。
ilter.java
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
@Autowired
CustomUserDetailsService userService;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
try {
CustomUserDetails user = new ObjectMapper().readValue(request.getInputStream(), CustomUserDetails.class);
return authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), new ArrayList<>()));
} catch (Exception e) {
}
return super.attemptAuthentication(request, response);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication auth) {
String loggedInUser = ((CustomUserDetails) auth.getPrincipal()).getUsername();
Claims claims = Jwts.claims().setSubject(loggedInUser);
if (loggedInUser != null) {
CustomUserDetails user = (CustomUserDetails) userService.loadUserByUsername(loggedInUser);
String roles[] = {};
for (Role role : user.getUser().getUserRoles()) {
roles[roles.length + 1] = role.getRole();
}
claims.put("roles", roles);
claims.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME));
}
String token = Jwts.builder().setClaims(claims)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET.getBytes()).compact();
response.addHeader(HEADER_STRING, TOKEN_PREFIX + token);
}
}
JWTAuthorizationFilter。JAVA
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
public JWTAuthorizationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
String header = request.getHeader(HEADER_STRING);
if (header == null || !header.startsWith(TOKEN_PREFIX)) {
chain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authentication = getToken(request);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
@SuppressWarnings("unchecked")
private UsernamePasswordAuthenticationToken getToken(HttpServletRequest request) {
String token = request.getHeader(HEADER_STRING);
System.out.println("-----------------------------------------------------");
System.out.println("Token: " + token);
System.out.println("-----------------------------------------------------");
if (token != null) {
Claims claims = Jwts.parser().setSigningKey(SECRET.getBytes())
.parseClaimsJws(token.replace(TOKEN_PREFIX, "")).getBody();
String user = claims.getSubject();
ArrayList<String> roles = (ArrayList<String>) claims.get("roles");
ArrayList<MyGrantedAuthority> rolesList = new ArrayList<>();
if (roles != null) {
for (String role : roles) {
rolesList.add(new MyGrantedAuthority(role));
}
}
if (user != null) {
return new UsernamePasswordAuthenticationToken(user, null, null);
}
return null;
}
return null;
}
}
SecurityConfig。JAVA
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Qualifier("userDetailsService")
@Autowired
CustomUserDetailsService userDetailsService;
@Autowired
PasswordEncoder passwordEncoder;
@Autowired
AuthenticationManager authenticationManager;
@Autowired
JWTAuthenticationEntryPoint jwtAuthenticationEntryPoint;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
try {
auth.userDetailsService(this.userDetailsService).passwordEncoder(passwordEncoder);
} catch (Exception e) {
}
}
/*
* @Autowired public void configureGlobal(AuthenticationManagerBuilder auth)
* throws Exception {
* auth.inMemoryAuthentication().withUser("student").password("student").roles(
* "student").and().withUser("admin") .password("admin").roles("admin"); }
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
// http.authorizeRequests().anyRequest().permitAll();
// http.authorizeRequests().antMatchers("/api/**").permitAll();
http.addFilter(new JWTAuthenticationFilter(authenticationManager));
http.addFilter(new JWTAuthorizationFilter(authenticationManager));
http.authorizeRequests().antMatchers("/api/student/**").hasAnyRole("STUDENT", "ADMIN");
http.authorizeRequests().antMatchers("/api/admin/**").hasRole("ADMIN");
http.authorizeRequests().antMatchers("/api/libararian/**").hasAnyRole("LIBRARIAN", "ADMIN");
http.authorizeRequests().antMatchers("/api/staff/**").hasAnyRole("STAFF", "ADMIN");
http.authorizeRequests().antMatchers("/api/teacher/**").hasAnyRole("TEACHER", "ADMIN");
http.authorizeRequests().antMatchers("/api/parent/**").hasAnyRole("PARENT", "ADMIN");
http.httpBasic().authenticationEntryPoint(jwtAuthenticationEntryPoint);
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// http.formLogin().and().logout().logoutSuccessUrl("/login?logout").permitAll();
}
}
我的授权。JAVA
public class MyGrantedAuthority implements GrantedAuthority {
String authority;
MyGrantedAuthority(String authority) {
this.authority = authority;
}
@Override
public String getAuthority() {
// TODO Auto-generated method stub
return authority;
}
}
oint.java
@Component
public class JWTAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
response.setStatus(403);
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
String message;
if (exception.getCause() != null) {
message = exception.getCause().getMessage();
} else {
message = exception.getMessage();
}
byte[] body = new ObjectMapper().writeValueAsBytes(Collections.singletonMap("error", message));
response.getOutputStream().write(body);
}
}
我还在我的项目中使用jwt身份验证,我可以看到您缺少一个应该在项目中使用的入口点。我将告诉您我是如何实现它的,并看看它是否能帮助您=)。您需要实现authenticationEntryPoint,以便告诉代码如何进行身份验证。它可以添加到http上的过滤器之后。授权请求,使用命令:
.authenticationEntryPoint(jwtAuthEndPoint);
其中jwtAuthEndPoint是以下组件:
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
AuthenticationException e) throws IOException, ServletException {
httpServletResponse.setStatus(SC_FORBIDDEN);
httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
String message;
if (e.getCause() != null) {
message = e.getCause().getMessage();
} else {
message = e.getMessage();
}
byte[] body = new ObjectMapper().writeValueAsBytes(Collections.singletonMap("error", message));
httpServletResponse.getOutputStream().write(body);
}
}
我还建议你看看这个教程,它在这种情况下帮助了我很多:https://sdqali.in/blog/2016/07/07/jwt-authentication-with-spring-web---part-4/
我明白了。我遵循了另一个让我的工作变得简单的教程。这是完整的重写工作代码
TokenProvider.java
package com.cloudsofts.cloudschool.security;
import static com.cloudsofts.cloudschool.security.SecurityConstants.EXPIRATION_TIME;
import static com.cloudsofts.cloudschool.security.SecurityConstants.SECRET;
import java.util.ArrayList;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import com.cloudsofts.cloudschool.people.users.pojos.CustomUserDetails;
import com.cloudsofts.cloudschool.people.users.pojos.Role;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
@Component
public class TokenProvider {
@Autowired
CustomUserDetailsService userService;
public String createToken(String username) {
CustomUserDetails user = (CustomUserDetails) userService.loadUserByUsername(username);
Claims claims = Jwts.claims().setSubject(username);
ArrayList<String> rolesList = new ArrayList<String>();
for (Role role : user.getUser().getUserRoles()) {
rolesList.add(role.getRole());
}
claims.put("roles", rolesList);
String token = Jwts.builder().setClaims(claims)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)).setIssuedAt(new Date())
.signWith(SignatureAlgorithm.HS512, SECRET).compact();
return token;
}
public Authentication getAuthentication(String token) {
String username = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody().getSubject();
UserDetails userDetails = this.userService.loadUserByUsername(username);
return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
}
}
JWTFilter。JAVA
package com.cloudsofts.cloudschool.security;
import static com.cloudsofts.cloudschool.security.SecurityConstants.HEADER_STRING;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.GenericFilterBean;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
public class JWTFilter extends GenericFilterBean {
public final static String AUTHORIZATION_HEADER = "Authorization";
private final TokenProvider tokenProvider;
public JWTFilter(TokenProvider tokenProvider) {
this.tokenProvider = tokenProvider;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
try {
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
String jwt = resolveToken(httpRequest);
if (jwt != null) {
Authentication authentication = this.tokenProvider.getAuthentication(jwt);
if (authentication != null) {
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
chain.doFilter(servletRequest, servletResponse);
} catch (ExpiredJwtException | UnsupportedJwtException | MalformedJwtException | SignatureException
| UsernameNotFoundException e) {
// Application.logger.info("Security exception {}", e.getMessage());
((HttpServletResponse) servletResponse).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
}
private String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader(HEADER_STRING);
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7, bearerToken.length());
}
return null;
}
}
JWTConfigurer。JAVA
import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.DefaultSecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
public class JWTConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
private final TokenProvider tokenProvider;
public JWTConfigurer(TokenProvider tokenProvider) {
this.tokenProvider = tokenProvider;
}
@Override
public void configure(HttpSecurity http) throws Exception {
JWTFilter customFilter = new JWTFilter(tokenProvider);
http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
}
}
SecurityConfig。JAVA
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.cloudsofts.cloudschool.people.users.pojos.User;
@RestController
public class LoginController {
private AuthenticationManager authenticationManager;
private TokenProvider tokenProvider;
private CustomUserDetailsService userService;
LoginController(AuthenticationManager auth, CustomUserDetailsService service, TokenProvider tokenProvider) {
this.authenticationManager = auth;
this.userService = service;
this.tokenProvider = tokenProvider;
}
@PostMapping("/login")
public String getToken(@RequestBody User user, HttpServletResponse response) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(user.getUsername(),
user.getPassword());
authenticationManager.authenticate(authToken);
return tokenProvider.createToken(user.getUsername());
}
}
登录ontroller.java
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.cloudsofts.cloudschool.people.users.pojos.User;
@RestController
public class LoginController {
private AuthenticationManager authenticationManager;
private TokenProvider tokenProvider;
private CustomUserDetailsService userService;
LoginController(AuthenticationManager auth, CustomUserDetailsService service, TokenProvider tokenProvider) {
this.authenticationManager = auth;
this.userService = service;
this.tokenProvider = tokenProvider;
}
@PostMapping("/login")
public String getToken(@RequestBody User user, HttpServletResponse response) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(user.getUsername(),
user.getPassword());
authenticationManager.authenticate(authToken);
return tokenProvider.createToken(user.getUsername());
}
}
链接到帮助我的Github项目。
注意:我的问题与Spring-Boot REST API+web应用程序的安全性有关。
我正在开发一个具有自己的身份验证和授权机制的REST应用程序。我想使用JSON Web Tokens进行身份验证。以下是有效且安全的实现吗? < li >将开发一个REST API来接受用户名和密码并进行认证。要使用的HTTP方法是POST,因此没有缓存。此外,在传输时还会有安全SSL < li >在认证时,将创建两个JWTs访问令牌和刷新令牌。刷新令牌将具有更长的有效期。这两个令牌都将写入coo
我读了一些关于“JWT vs Cookie”的帖子,但它们只会让我更加困惑…… > 我想澄清一下,当人们谈论“基于令牌的身份验证与cookie”时,这里的cookie仅指会话cookie?我的理解是,cookie就像一个介质,它可以用来实现基于令牌的身份验证(在客户端存储可以识别登录用户的东西)或者基于会话的身份验证(在客户端存储与服务器端会话信息匹配的常量) 为什么我们需要JSON web令牌?
本文向大家介绍Asp.Net Core中基于Session的身份验证的实现,包括了Asp.Net Core中基于Session的身份验证的实现的使用技巧和注意事项,需要的朋友参考一下 在Asp.Net框架中提供了几种身份验证方式:Windows身份验证、Forms身份验证、passport身份验证(单点登录验证)。 每种验证方式都有适合它的场景: 1.Windowss身份验证通常用于企业内部环境,
**有人可以建议我另一个解决方案,或者我如何可以解决这个问题please.and感谢提前主计长 服务 网络安全配置 错误**说明: com中的Field authenticationManager。实例演示。服务JwtService需要“org”类型的bean。springframework。安全认证。找不到AuthenticationManager。 注入点有以下注释:-@org。springf