Java Spring boot如何使用jwt管理用户角色
我正在用spring boot编写一个RESTful api。 我使用的是spring boot、jersey、mongo db、swagger、spring boot security和jwt 我已经为数据库的请求编写了模型和存储库。现在我已经集成了安全性和jwt令牌 现在我需要离散用户的角色,因为用户不能调用需要管理员权限的路由 我有一个登录的路径,它是返回令牌。这是我的SecurityConfig的代码Java Spring boot如何使用jwt管理用户角色,java,spring-boot,spring-security,jwt,roles,Java,Spring Boot,Spring Security,Jwt,Roles,我正在用spring boot编写一个RESTful api。 我使用的是spring boot、jersey、mongo db、swagger、spring boot security和jwt 我已经为数据库的请求编写了模型和存储库。现在我已经集成了安全性和jwt令牌 现在我需要离散用户的角色,因为用户不能调用需要管理员权限的路由 我有一个登录的路径,它是返回令牌。这是我的SecurityConfig的代码 ... @Configuration @EnableWebSecurity publi
...
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
UserRepository userRepository;
@Override
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable().authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/api/swagger.json").permitAll()
.antMatchers(HttpMethod.POST, "/login").permitAll()
.antMatchers("/api/*").authenticated()
.and()
.addFilterBefore(new JWTLoginFilter("/login", authenticationManager(), userRepository),
UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class);
}
}
我编写了JWTLoginFilter,它在用户登录时返回令牌
...
@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException, IOException, ServletException {
Credential creds = new ObjectMapper().readValue(req.getInputStream(), Credential.class);
User user = userRepository.login(creds);
if (user == null)
throw new BadCredentialsException("");
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
creds.getUsername(),
creds.getPassword()
);
return token;
}
...
我想在方法上的端点类上插入此项
@PreAuthorize("hasRole('ROLE_ADMIN')")
这是端点的一部分
....
@Component
@Path("story")
@Api(value = "Story", produces = "application/json")
public class StoryEndpoint {
private static final Logger LOGGER = LoggerFactory.getLogger(StoryEndpoint.class);
@Autowired
StoryRepository storyRepository;
@GET
@Path("/")
@Produces(MediaType.APPLICATION_JSON)
@PreAuthorize("hasRole('ROLE_ADMIN')") <--- I want insert here
@ApiOperation(value = "Get All Story", response = Story.class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "hello resource found"),
@ApiResponse(code = 404, message = "Given admin user not found")
})
public Response getAllStory(){
Iterable<Story> stories = storyRepository.findAll();
LOGGER.info("getAllStory");
return (stories!=null) ? Response.ok(stories).build() : Response.ok(ResponseErrorGenerator.generate(Response.Status.NOT_FOUND)).status(Response.Status.NOT_FOUND).build();
}
....
。。。。
@组成部分
@路径(“故事”)
@Api(value=“Story”,products=“application/json”)
公共类脚本端点{
私有静态最终记录器Logger=LoggerFactory.getLogger(StoryEndpoint.class);
@自动连线
故事库;
@得到
@路径(“/”)
@产生(MediaType.APPLICATION_JSON)
@预授权(“hasRole('ROLE_ADMIN')”)您需要将用户角色作为附加声明存储在JWT令牌中,在令牌验证后提取它们,并作为主体的“权限”传递:
Collection<? extends GrantedAuthority> authorities
= Arrays.asList(claims.get(AUTHORITIES_KEY).toString().split(",")).stream()
.map(authority -> new SimpleGrantedAuthority(authority))
.collect(Collectors.toList());
User principal = new User(claims.getSubject(), "",
authorities);
UsernamePasswordAuthenticationToken t
= new UsernamePasswordAuthenticationToken(principal, "", authorities);
Collection您应该将角色添加到令牌中,例如,您可以参考以下链接:-
首先需要在JWT中添加角色。为此,您可以在JWT生成器类中添加声明
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
Set<String> Userroles = new HashSet<>();
User user = userRepository.findByUsername(userDetails.getUsername());
for(Role role:user.getRoles()){
Userroles.add(role.getName());
}
claims.put("Roles",Userroles.toArray());
return createToken(claims, userDetails.getUsername());
}
private String createToken(Map<String, Object> claims, String subject) {
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();
}
请检查此Github Repo()以供参考。不要将权限和角色(即带有“ROLE\u”前缀的权限)混合使用,请使用hasRole('ADMIN')
或hasAuthority('ROLE\u ADMIN'))
。我需要修改我的用户类?我还没有理解代码的第一部分。我在哪里插入这段代码?@Alex ChemyshevFirst部分代码是关于角色名的提取列表,以“,”分隔。您应该放置此代码,而不是“UsernamePasswordAuthenticationToken=new UsernamePasswordAuthenticationToken”(creds.getUsername(),creds.getPassword())'但您还需要将角色列表添加到JWT令牌中,否则它将不起作用。可能Spring和JWT auth的完整解决方案将更好地帮助您:我尝试更改代码,但它不起作用,并且没有收到错误。我无法理解我的错误所在。您需要在此处放置登录而不是整个对象
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "USER_ROLES", joinColumns = {
@JoinColumn(name = "USER_ID") }, inverseJoinColumns = {
@JoinColumn(name = "ROLE_ID") })
private Set<Role> roles;
User findByUsername(String username);