Azure Linux PHP Web应用后端AD鉴权403问题及权限验证需求
问题分析与解决方案
一、后端调用/.auth/me返回403的原因
后端PHP调用/.auth/me报403,核心原因是后端请求没带对会话Cookie。前端JS能跑通是因为浏览器自动帮你带了AppServiceAuthSession Cookie,但PHP发起的curl请求默认不会继承这个Cookie,身份验证模块自然不认,直接返回403。另外,Azure App Service的内置auth模块对后端请求的校验逻辑和前端不一样,后端得主动把身份凭证带上才行。
二、后端实现用户权限校验的两种可行方法
方法1:修复/.auth/me的后端调用
要让PHP能成功调用/.auth/me,手动把AppServiceAuthSession Cookie传进去就行,代码示例:
// 先从当前请求里拿auth会话的Cookie $authCookie = $_COOKIE['AppServiceAuthSession'] ?? ''; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, 'https://' . $_SERVER['HTTP_HOST'] . '/.auth/me'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 关键:带上身份Cookie curl_setopt($ch, CURLOPT_COOKIE, 'AppServiceAuthSession=' . $authCookie); $response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($httpCode === 200) { $userData = json_decode($response, true); // 从返回的用户数据里提取UPN或者ObjectID,后面调用Graph API要用 $userUpn = ''; foreach ($userData[0]['user_claims'] as $claim) { if ($claim['typ'] === 'upn') { $userUpn = $claim['val']; break; } } } else { http_response_code(403); exit('无权访问'); }
注意:如果你的Web App开了HTTPS,curl请求一定要用HTTPS,别搞混合内容。
方法2:用应用服务主体通过Graph API查用户组
既然你已经配好了能访问Graph API的应用服务主体,这方法比调用/.auth/me更可靠,具体步骤:
- 先拿应用服务主体的Graph令牌:
$tenantId = '你的租户ID'; $clientId = '应用服务主体的ID'; $clientSecret = '应用服务主体的密钥'; $tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"; $postData = [ 'grant_type' => 'client_credentials', 'client_id' => $clientId, 'client_secret' => $clientSecret, 'scope' => 'https://graph.microsoft.com/.default' ]; $ch = curl_init($tokenUrl); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($postData)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $tokenResponse = json_decode(curl_exec($ch), true); curl_close($ch); $graphToken = $tokenResponse['access_token'] ?? '';
- 调用Graph API检查用户是否在目标组里:
先从/.auth/me或者前端传过来的参数里拿到用户的Azure AD ObjectID,然后调用checkMemberGroups接口:
$userId = '用户的Azure AD Object ID'; $targetGroupId = '你要校验的组ID'; $graphUrl = "https://graph.microsoft.com/v1.0/users/$userId/checkMemberGroups"; $postData = json_encode(['groupIds' => [$targetGroupId]]); $ch = curl_init($graphUrl); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, $postData); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $graphToken, 'Content-Type: application/json' ]); $groupCheckResponse = json_decode(curl_exec($ch), true); curl_close($ch); // 看返回结果里有没有目标组ID,有就是有权限 if (in_array($targetGroupId, $groupCheckResponse['value'] ?? [])) { // 放行,显示管理员页面 } else { http_response_code(403); exit('无管理员权限'); }
三、踩坑提醒
- 应用服务主体必须要有
Directory.Read.All的应用权限(不是委托权限),不然调用Graph API会报错,得去Azure AD的应用注册里配置好权限并授予管理员同意。 - 别把客户端密钥硬写在代码里,丢去Azure App Service的配置项(Configuration > Application settings)里存,用
getenv('CLIENT_SECRET')取就行,安全多了。 - 如果之前开IP限制导致应用访问不了自己,现在关了之后要是Graph API还有IP问题,可以去应用注册的企业应用里加信任IP范围,或者把Web App的出站IP加进允许列表。
内容的提问来源于stack exchange,提问作者kithril
相关产品推荐
相关产品推荐

