dromara/Sa-Token · error · SaOAuth2Exception

30151

30151

Error message

无效请求方式:

What it means

Thrown by SaOAuth2ServerProcessor.doConfirm: the authorization-confirm endpoint accepts POST only. A GET request (e.g. a browser navigation or a form defaulting to GET) hits this guard before any confirmation logic runs. Error code 30151.

Source

Thrown at sa-token-plugin/sa-token-oauth2/src/main/java/cn/dev33/satoken/oauth2/processor/SaOAuth2ServerProcessor.java:250

	}

	/**
	 * doConfirm 确认授权接口
	 * @return 处理结果
	 */
	public Object doConfirm() {
		// 获取变量
		SaRequest req = SaHolder.getRequest();
		String clientId = req.getParamNotNull(Param.client_id);
		Object loginId = SaOAuth2Manager.getStpLogic().getLoginId();
		String scope = req.getParamNotNull(Param.scope);
		List<String> scopes = SaOAuth2Manager.getDataConverter().convertScopeStringToList(scope);
		SaOAuth2DataGenerate dataGenerate = SaOAuth2Manager.getDataGenerate();
		SaOAuth2Template oauth2Template = SaOAuth2Manager.getTemplate();

		// 此请求只允许 POST 方式
		if(!req.isMethod(SaHttpMethod.POST)) {
			throw new SaOAuth2Exception("无效请求方式:" + req.getMethod()).setCode(SaOAuth2ErrorCode.CODE_30151);
		}

		// 确认授权
		oauth2Template.saveGrantScope(clientId, loginId, scopes);

		// 判断所需的返回结果模式
		boolean buildRedirectUri = req.isParam(Param.build_redirect_uri, "true");

		// -------- 情况1:只返回确认结果即可
		if( ! buildRedirectUri ) {
			oauth2Template.saveGrantScope(clientId, loginId, scopes);
			return SaResult.ok();
		}

		// -------- 情况2:需要返回最终的 redirect_uri 地址

		// 构建请求 Model
		RequestAuthModel ra = SaOAuth2Manager.getDataResolver().readRequestAuthModel(req, loginId);

View on GitHub (pinned to ac2c7f6e94)

Solutions

  1. Change the confirm form to method="POST" with client_id and scope fields
  2. For AJAX confirm, use fetch/axios with method POST
  3. Keep required params (client_id, scope, build_redirect_uri) in the POST body

Example fix

<!-- before -->
<form action="/oauth2/doConfirm">
  ...
</form>

<!-- after -->
<form action="/oauth2/doConfirm" method="post">
  <input name="client_id" value="1001">
  <input name="scope" value="getuserinfo">
</form>
Defensive patterns

Strategy: validation

Validate before calling

// front-end: always submit confirm via POST
<form method="post" action="/oauth2/doConfirm">...</form>
// or: await fetch('/oauth2/doConfirm', { method: 'POST', body: new FormData(form) });

Try / catch

catch(SaOAuth2Exception e) { if("30151".equals(e.getCode())) res.setStatus(405).setBody("POST required"); }

Prevention

When it happens

Trigger: Submitting the consent/confirm page as a GET request, or a custom front-end sending an AJAX GET to /oauth2/doConfirm. Form without method="post" is the classic case.

Common situations: Hand-written consent HTML page using a plain link or default GET form; curl examples in documentation using GET; a redirect from the login page turning the confirm submit into a GET.

Related errors


AI-assisted analysis of dromara/Sa-Token@ac2c7f6e94 (2026-08-14). Data as JSON: /api/errors/ff3cfaddb214a35b. Report an issue: GitHub.