授权仅适用于GET请求

时间:2018-12-06 13:09:19

标签: java angular rest spring-boot

我的rest控制器中具有以下方法:

第一个是获取请求:

@GetMapping
public ResponseEntity<PagedResponse<Shop>> getAllShops() {
    return ResponseEntity.ok(this.shopService.getAllShopsSortedByDistance());
}

第二个是发帖请求:

@PostMapping("/like")
public ResponseEntity<RestResponse> addShop(@RequestParam(value = "shop") String shopId,
                                            @CurrentUser UserPrincipal userPrincipal)
{
    RestResponse restResponse = this.shopService.addShopToLikedShops(shopId, userPrincipal.getId());
    UriComponents uriComponents = uriComponentsBuilder.path("/shops").buildAndExpand();
    return ResponseEntity.created().body(restResponse);
}

在角度服务中,我拨打了以下电话:

getAllShops(): Observable<ShopsPage> {
    const httpOptions = {
        headers: new HttpHeaders({
            'Authorization': this.tokenService.getToken()
        })
    };
    return this.httpClient.get<ShopsPage>(this.apiUrl, httpOptions)
            .pipe(map(response => {
                return response;
            }));
    }

此方法在控制器中调用get方法,并且工作正常。
第二种服务方法:

addShopToPreferred(shopId: string): Observable<any> {
    const httpOptions = {
        headers: new HttpHeaders({
            'Content-Type': 'application/json',
            'Authorization': this.tokenService.getToken()
        })
    };
    return this.httpClient.post(this.apiUrl + "/like?shop=" + shopId, httpOptions)
        .pipe(map(response => {
            return response;
        }));
}

此服务方法调用了post controller方法,但没有用,这是错误信息:

  

错误:{状态:“未经授权”,错误:401,消息:“对不起,您无权访问此资源。”}

我不知道为什么令牌只能在GET上工作,而不能在POST上工作。

编辑
春季安全配置:

@Override
protected void configure(HttpSecurity http) throws Exception {
        http
                .cors()
                .and()
                .csrf()
                .disable()
                .exceptionHandling()
                .authenticationEntryPoint(this.jwtAuthenticationEntryPoint)
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/users/**")
                .permitAll()
                .anyRequest()
                .authenticated();

        // Add our custom JWT security filter
        http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }

编辑2
添加JwtAuthenticationFilter类:

public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private JwtTokenProvider tokenProvider;

    @Autowired
    private CustomUserDetailsService customUserDetailsService;

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

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            String jwt = getJwtFromRequest(request);

            if (StringUtils.hasText(jwt) && this.tokenProvider.validateToken(jwt)) {
                String userId = this.tokenProvider.getUserIdFromJWT(jwt);

                UserDetails userDetails = this.customUserDetailsService.loadUserById(userId);
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        } catch (Exception ex) {
            logger.error("Could not set user authentication in security context", ex);
        }

        filterChain.doFilter(request, response);
    }

    private String getJwtFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}

1 个答案:

答案 0 :(得分:0)

这是一个愚蠢的错误,angular的GET方法接受两个参数:

getAllShops(url, headers)

但是POST接受三个:

addShop(url, data, headers)

所以我传递的是数据而不是标题,这是post方法的样子:

addShopToPreferred(shopId: string): Observable<any> {
    const httpOptions = {
        headers: new HttpHeaders({
            'Content-Type': 'application/json',
            'Authorization': this.tokenService.getToken()
        })
    };
    return this.httpClient.post(this.apiUrl + "/like?shop=" + shopId, null, httpOptions)
        .pipe(map(response => {
            return response;
        }));
}