我正在 Symfony2 中使用 FOSRest 和 FOSOauthServer 包(......以及许多其他)开发一个 RESTful Web 服务。我的问题是,使用其他用户的访问令牌,api 会给出响应而不是 403 状态码。例如:
我有两个用户存储在数据库中
用户A 和令牌A 用户B 和令牌B
示例请求 http://example.com/api/v1/userA/products?access_token=tokenB
当前响应
{
products: {
0: { ... }
1: { ... }
}
}
但是我正在使用用户 B 的访问令牌请求用户 A 的产品。我如何检查提供的访问令牌是否属于产品所有者?
我的 security.yml 文件:
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
role_hierarchy:
MY_ROLE:
# ...
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_SONATA_ADMIN, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
SONATA:
- ROLE_SONATA_PAGE_ADMIN_PAGE_EDIT
providers:
fos_userbundle:
id: fos_user.user_provider.username_email
firewalls:
admin:
pattern: /admin(.*)
context: user
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
login_path: /admin/login
use_forward: false
check_path: /admin/login_check
failure_path: null
logout:
path: /admin/logout
anonymous: true
# FOSOAuthBundle and FOSRestBundle
oauth_token:
pattern: ^/oauth/v2/token
security: false
# oauth_authorize: commented because there are not oauth login form on this app
# pattern: ^/oauth/v2/auth
# Add your favorite authentication process here
api:
pattern: ^/api
fos_oauth: true
stateless: true
anonymous: false
# This firewall is used to handle the public login area
# This part is handled by the FOS User Bundle
main:
# ...
access_control:
# ...
# API (FOSRestBundle and FOSOAuthBundle)
- { path: ^/api, roles: [IS_AUTHENTICATED_FULLY] }
我在 ApiBundle 上的 routing.yml
# API Endpoints
app_api_user_get_products:
pattern: /{username}/products
defaults: { _controller: ApiBundle:User:getProducts, _format: json }
methods: GET
我的 UserController.php
<?php
namespace App\ApiBundle\Controller;
Use App\MainBundle\Entity\Product;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
// ... more use statments
class UserController extends ApiController {
/**
* List user's products.
*
* @ApiDoc(
* resource = true,
* description="This method must have the access_token parameter. The parameters limit and offset are optional.",
* filters={
* {"name"="access_token", "dataType"="string", "required"="true"},
* {"name"="offset", "dataType"="integer", "default"="0", "required"="false"},
* {"name"="limit", "dataType"="integer", "default"="250", "required"="false"}
* },
* )
*
* @Annotations\QueryParam(name="offset", requirements="\d+", nullable=true, description="Offset from which to start listing products.")
* @Annotations\QueryParam(name="limit", requirements="\d+", default="500", description="How many products to return.")
*
* @Annotations\View()
*
* @param User $user the request object
* @param ParamFetcherInterface $paramFetcher param fetcher service
*
* @return array
*/
public function getProductsAction(User $user, ParamFetcherInterface $paramFetcher, Request $request) {
// $offset = $paramFetcher->get('offset');
// $offset = null == $offset ? 0 : $offset;
// $limit = $paramFetcher->get('limit');
try {
// estructure and exclude fields strategy http://jmsyst.com/libs/serializer/master/cookbook/exclusion_strategies
$data = array('products' => array());
foreach ($user->getCatalog() as $p) {
if ($p->getAvailable() == true) {
$product = $p->getProduct();
$data['products'][] = array(
'id' => $product->getId(),
'reference' => $product->getReference(),
'brand' => $product->getBrand(),
'description' => $product->getDescription(),
// ...
);
}
}
} catch (\Exception $e) {
throw new HttpException(Codes::HTTP_INTERNAL_SERVER_ERROR, $e->getTraceAsString());
}
// New view
$view = new View($data);
$view->setFormat('json');
return $this->handleView($view);
}
}
非常感谢你的帮助!