web-dev-qa-db-ja.com

SpringBootでユーザーロールをjwtで管理する方法

SpringBootを使用してRESTfulAPIを作成しています。 Spring Boot、Jersey、Mongo DB、Swagger、Spring Boot Security、JWTを使用しています。

DBへのリクエストのモデルであるリポジトリを作成しました。これで、セキュリティトークンとjwtトークンが統合されました。

ユーザーは管理者権限を必要とするルートを呼び出すことができないため、ここでユーザーの役割を離散化する必要があります。

ログイン用のルートがあります。トークンが返されます。これは私のSecurityConfigのコードです

...
@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();
    }
....

ユーザーにロールを割り当てるメカニズムを作成するにはどうすればよいですか?また、トークンでロールを渡し、ユーザーのロールをルート上で離散化するにはどうすればよいですか?

3
Marco Ferraioli

追加のクレームとして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);
6
Alex Chernyshev

トークンに役割を追加する必要があります。たとえば、次のリンクを参照できます: http://www.svlada.com/jwt-token-authentication-with-spring-boot/

2
Anshul Sharma