如何使用Spring安全和JWT打开post路由?

4ioopgfo  于 2023-08-02  发布在  Spring
关注(0)|答案(1)|浏览(83)

我已经配置了我的应用程序的安全性,我试图实现只有具有角色“CHEF”的用户才能在特定的post方法上添加新数据。
我设置csrf禁用,并在过滤器启用它之前。但它不起作用。
这是我的配置类:

@Configuration
@EnableMethodSecurity
public class WebSecurityConfig {

    @Autowired
    UserDetailsServiceCustom userDetailsService;

    @Autowired
    private AuthEntryPointJwt unauthorizedHandler;

    @Bean
    public AuthTokenFilter authenticationJwtTokenFilter() {
        return new AuthTokenFilter();
    }

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();

        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setPasswordEncoder(passwordEncoder());

        return authProvider;
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
        return authConfig.getAuthenticationManager();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf(csrf -> csrf.disable())
                .exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .authorizeHttpRequests(auth -> auth.requestMatchers("/api/auth/**").permitAll()
                        .requestMatchers(HttpMethod.POST, "/api/receitas/add").hasAnyRole("CHEF")
                        .requestMatchers("/api/receitas/**").permitAll()
                        .anyRequest().authenticated());

        http.authenticationProvider(authenticationProvider());

        http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        http.addFilterAfter(new CsrfTokenResponseHeaderBindingFilter(), CsrfFilter.class);

        return http.build();
    }

}

字符串
Auth入口点:

@Component
public class AuthEntryPointJwt implements AuthenticationEntryPoint {

    private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class);

    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authException)
            throws IOException, ServletException {
        logger.error("Unauthorized error: {}", authException.getMessage());
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error: Unauthorized");
    }

}


这是我的控制器类:

@RestController
@RequestMapping("/api/receitas")
@CrossOrigin(origins = "*", maxAge = 3600)
public class ReceitaController {

    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    private ReceitaService receitaService;

    @GetMapping("/listar")
    public ResponseEntity<?> listar() {

        List<Receita> receitas = receitaService.findAll();

        return new ResponseEntity<List<Receita>>(receitas, HttpStatus.OK);
    }

    @GetMapping("/chef")
    @PreAuthorize("hasRole('CHEF')")
    public ResponseEntity<?> teste() {

        return new ResponseEntity<String>("Chef autorizado", HttpStatus.OK);
    }

    @PostMapping("/add")
    @PreAuthorize("hasRole('CHEF')")
    public ResponseEntity<?> salvar(@RequestBody CreateReceitaDTO receita) {
        System.out.println("tentando fazer " + receita.getName());

        try {
            Receita newReceita = receitaService.createReceita(receita);

            return new ResponseEntity<Receita>(newReceita, HttpStatus.CREATED);
        } catch (Exception e) {
            ExceptionResponse exception = new ExceptionResponse(e.getMessage(), HttpStatus.BAD_REQUEST);

            return new ResponseEntity<ExceptionResponse>(exception, HttpStatus.BAD_REQUEST);
        }
    }
}


我的JWt utils类:

@Component
public class JwtUtils {
    private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);

    @Value("${teles.app.jwtSecret}")
    private String jwtSecret;

    @Value("${teles.app.jwtExpirationMs}")
    private int jwtExpirationMs;

    @Value("${teles.app.jwtCookieName}")
    private String jwtCookie;

    public String getJwtFromCookies(HttpServletRequest request) {
        Cookie cookie = WebUtils.getCookie(request, jwtCookie);
        if (cookie != null) {
            return cookie.getValue();
        } else {
            return null;
        }
    }

    public ResponseCookie generateJwtCookie(UserDetailsCustom userPrincipal) {
        String jwt = generateTokenFromUsername(userPrincipal.getUsername());
        ResponseCookie cookie = ResponseCookie.from(jwtCookie, jwt).path("/api").maxAge(24 * 60 * 60).httpOnly(true)
                .build();
        return cookie;
    }

    public ResponseCookie getCleanJwtCookie() {
        ResponseCookie cookie = ResponseCookie.from(jwtCookie, null).path("/api").build();
        return cookie;
    }

    public String getUserNameFromJwtToken(String token) {
        return Jwts.parserBuilder().setSigningKey(key()).build()
                .parseClaimsJws(token).getBody().getSubject();
    }

    private Key key() {
        return Keys.hmacShaKeyFor(Decoders.BASE64.decode(jwtSecret));
    }

    public boolean validateJwtToken(String authToken) {
        try {
            Jwts.parserBuilder().setSigningKey(key()).build().parse(authToken);
            return true;
        } catch (MalformedJwtException e) {
            logger.error("Invalid JWT token: {}", e.getMessage());
        } catch (ExpiredJwtException e) {
            logger.error("JWT token is expired: {}", e.getMessage());
        } catch (UnsupportedJwtException e) {
            logger.error("JWT token is unsupported: {}", e.getMessage());
        } catch (IllegalArgumentException e) {
            logger.error("JWT claims string is empty: {}", e.getMessage());
        }

        return false;
    }

    public String generateTokenFromUsername(String username) {
        try {
            return Jwts.builder()
                    .setSubject(username)
                    .setIssuedAt(new Date())
                    .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
                    .signWith(key(), SignatureAlgorithm.HS256)
                    .compact();
        } catch (Exception e) {
            throw new RuntimeException("Error while generation token", e);
        }

    }
}


当我尝试执行POST方法时,会出现以下消息:“未经授权的错误:访问此资源“”需要完全身份验证。但是当我用相同的预授权做GET时,我得到的状态是200。

k0pti3hp

k0pti3hp1#

为什么你没有得到这个错误消息在GET请求到相同的请求Map是在requestMachers,你有,检查附加的截图,但对于其他端点,你没有任何角色的限制。


的数据

相关问题