我正在编写一个后端/APIRest,它是个人应用程序的一部分。我正在尝试通过JWT设置一个身份验证,角色为:ADMIN和USER。因为我只想为角色ADMIN筛选以下端点:/users/all
但当我发送我的http请求从失眠应用程序,与localhost:7777/users/all
我有一个错误403禁止.我不知道为什么.
这是一个由我发送的请求生成的JWT,你可以在jwt.io上查看它:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJrZW50MSIsInJvbGVzIjoiQURNSU4iLCJleHAiOjE2NjExNTUxNDUyOTUsImlhdCI6MTY2MDA3NTE0NTI5NX0.RGJzJVkM6bB0g6YlK6FFMzbjjTZ8qPqGf9pfHMeKHfyDV_OM9lF1w8SDzys3SC-iNdBMgXMjVP972URcISwJ_A
{1}/{2}相关终点控制器{3}/{4}
@RestController
@RequestMapping("/users")
public class AppUserController {
@RolesAllowed("ADMIN")
@GetMapping("/all")
public ResponseEntity<List<AppUserListDto>> getAllAppUsers() {
logger.info("GET /users/all");
return new ResponseEntity<List<AppUserListDto>>(appUserServiceImpl.getAllUsers(), HttpStatus.OK);
}
}
/* 安全配置 */
@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(
prePostEnabled = true,
securedEnabled = true,
jsr250Enabled = true)
public class SecurityConfiguration {
@Autowired
RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Autowired
JwtFilter jwtFilter;
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
http.csrf().disable().exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/users/add").permitAll()
.antMatchers("/users/all").hasRole("ADMIN")
.anyRequest().authenticated();
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public RoleHierarchy roleHierarchy() {
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
String hierarchy = "ADMIN > USER";
roleHierarchy.setHierarchy(hierarchy);
return roleHierarchy;
}
@Bean
public DefaultWebSecurityExpressionHandler webSecurityExpressionHandler() {
DefaultWebSecurityExpressionHandler expressionHandler = new DefaultWebSecurityExpressionHandler();
expressionHandler.setRoleHierarchy(roleHierarchy());
return expressionHandler;
}
}
/* 我的用户详细信息服务 */
@Service
public class MyUserDetailService implements UserDetailsService {
@Autowired
AppUserRepository appUserRepository;
@Autowired
RoleRepository roleRepository;
@Override
public UserDetails loadUserByUsername(String appUsername) throws UsernameNotFoundException {
AppUserEntity appUser = appUserRepository.findByAppUsername(appUsername);
if (appUser == null) {
return new org.springframework.security.core.userdetails.User(
" ", " ", true, true, true, true,
getAuthorities(Arrays.asList(
roleRepository.findByRoleName("USER"))));
}
return new org.springframework.security.core.userdetails.User(
appUser.getAppUsername(), appUser.getPassword(), true, true, true,
true, getAuthorities(appUser.getRoles()));
}
private Collection<? extends GrantedAuthority> getAuthorities(
Collection<Role> roles) {
return getGrantedAuthorities(getPrivileges(roles));
}
private List<String> getPrivileges(Collection<Role> roles) {
List<String> privileges = new ArrayList<>();
List<Privilege> collection = new ArrayList<>();
for (Role role : roles) {
privileges.add(role.getRoleName());
collection.addAll(role.getPrivileges());
}
for (Privilege item : collection) {
privileges.add(item.getName());
}
return privileges;
}
private List<GrantedAuthority> getGrantedAuthorities(List<String> privileges) {
List<GrantedAuthority> authorities = new ArrayList<>();
for (String privilege : privileges) {
authorities.add(new SimpleGrantedAuthority(privilege));
}
return authorities;
}
}
/* JWT 实用程序 */
@Component
public class JwtUtils {
@Autowired
AppUserRepository appUserRepository;
long JWT_VALIDITY = 5 * 60 * 60 * 60;
@Value("${jwt.secret}")
String secret;
private final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
public String generateToken(Authentication authentication) {
Map<String, Object> claims = new HashMap<>();
claims.put("roles",authentication.getAuthorities().stream().map(role -> role.getAuthority()).findFirst().orElseThrow(NoSuchElementException::new));
claims.put("iat",new Date(System.currentTimeMillis()));
claims.put("exp", new Date(System.currentTimeMillis() + JWT_VALIDITY * 1000));
claims.put("sub", authentication.getName());
Map<String, Object> headerJwt = new HashMap<>();
headerJwt.put("alg", "HS512");
headerJwt.put("typ", "JWT");
//TODO Later : Header, claims, jwt... will be Base64urlEncoded
return Jwts.builder()
.setHeader(headerJwt)
.setClaims(claims)
.signWith(SignatureAlgorithm.HS512, secret).compact();
}
public Authentication getAuthentication(String token) {
Claims claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
AppUserEntity appUser = appUserRepository.findByAppUsername(claims.getSubject());
logger.info("THIS IS THE SUBJECT FROM CLAIMS : {}", claims.getSubject());
Collection<? extends GrantedAuthority> authorities = getAuthorities(appUser.getRoles());
User principal = new User(claims.getSubject(), "", authorities);
return new UsernamePasswordAuthenticationToken(principal, token, authorities);
}
private Collection<? extends GrantedAuthority> getAuthorities(
Collection<Role> roles) {
return getGrantedAuthorities(getPrivileges(roles));
}
private List<String> getPrivileges(Collection<Role> roles) {
List<String> privileges = new ArrayList<>();
List<Privilege> collection = new ArrayList<>();
for (Role role : roles) {
privileges.add(role.getRoleName());
collection.addAll(role.getPrivileges());
}
for (Privilege item : collection) {
privileges.add(item.getName());
}
return privileges;
}
private List<GrantedAuthority> getGrantedAuthorities(List<String> privileges) {
List<GrantedAuthority> authorities = new ArrayList<>();
for (String privilege : privileges) {
authorities.add(new SimpleGrantedAuthority(privilege));
}
return authorities;
}
}
/*JWT控制器 */
@RestController
public class JwtController {
@Autowired
JwtUtils jwtUtils;
@Autowired
AuthenticationManagerBuilder authenticationManagerBuilder;
@PostMapping("/login")
public ResponseEntity<?> createAuthToken(@RequestBody JwtRequest jwtRequest) {
Authentication authentication = logUser(jwtRequest.getAppUsername(), jwtRequest.getPassword());
String jwt = jwtUtils.generateToken(authentication);
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(AUTHORIZATION_HEADER, "Bearer " + jwt);
Object principal = authentication.getPrincipal();
return new ResponseEntity<>(new JwtResponse(((User) principal).getUsername()), httpHeaders, HttpStatus.OK);
}
public Authentication logUser(String appUsername, String password) {
Authentication authentication = authenticationManagerBuilder.getObject()
.authenticate(new UsernamePasswordAuthenticationToken(appUsername, password));
SecurityContextHolder.getContext().setAuthentication(authentication);
return authentication;
}
}
/*JWT筛选器 */
@Component
public class JwtFilter extends OncePerRequestFilter {
@Autowired
JwtUtils jwtUtils;
public static final String AUTHORIZATION_HEADER = "Authorization";
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
String jwt = resolveToken(request);
if (StringUtils.hasText(jwt)) {
Authentication authentication = jwtUtils.getAuthentication(jwt);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(request, response);
}
private String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader(AUTHORIZATION_HEADER);
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7);
}
return null;
}
}
1条答案
按热度按时间r7knjye21#
解码后的令牌如下所示:
据我所知,问题出在用户角色上。您的角色应该是这样的格式:
在设置了
@RolesAllowed("ADMIN")
注解的情况下,此零件:则不需要。
顺便说一句,在您的
JwtUtils
类中,我注意到了下面这行代码:通过这行代码,您可以设置
列表作为map中“roles”键的值。由于该列表将包含整个
GrantedAuthority
对象,因此这不是Spring所期望的。假设您的role表如下所示:您可以执行以下操作:
这将解决我刚才描述问题。