自定义 oauth2 令牌请求以接受额外数据
Customise oath2 token request to accept extra data
我正在使用具有 spring 安全性的球衣和 spring-oauth2。我的应用程序在端点“/oauth/token”下运行良好。
我想更改端点以接受更多数据。要求是,我想向令牌 API 发送更多详细信息(即设备详细信息 OS、phone/tablet/web 等)。所以,我想覆盖端点,如果身份验证成功,我想将该额外信息存储在数据库中。
我找不到与以这种方式更改 API 相关的任何内容。
有人可以帮忙吗?
我找到了一个解决方案,方法是编写一个包装器控制器并分配默认的 tokenEndpoint bean
@FrameworkEndpoint
public class LoginContrller{
private static Logger logger = org.slf4j.LoggerFactory.getLogger(LoginContrller.class);
private WebResponseExceptionTranslator providerExceptionHandler = new DefaultWebResponseExceptionTranslator();
@Autowired
private UserManager userManager;
@Autowired
TokenEndpoint tokenEndPoint;
@RequestMapping(value = "/user/login", method=RequestMethod.POST,consumes=MediaType.APPLICATION_JSON)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
Map<String, String> parameters,@RequestBody(required=false) LoginModel loginModel) throws HttpRequestMethodNotSupportedException {
ResponseEntity<OAuth2AccessToken> response = tokenEndPoint.postAccessToken(principal, parameters);
if(!isRefreshTokenRequest(parameters)){
if(loginModel!=null){
loginModel.setUsername(parameters.get("username"));
try {
userManager.loginUser(loginModel);
} catch (UserNotFoundException e) {
logger.warn("Exception in custom login {} ",e);
}
}
}
return response;
}
private boolean isRefreshTokenRequest(Map<String, String> parameters) {
return "refresh_token".equals(parameters.get("grant_type")) && parameters.get("refresh_token") != null;
}
private boolean isAuthCodeRequest(Map<String, String> parameters) {
return "authorization_code".equals(parameters.get("grant_type")) && parameters.get("code") != null;
}
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public void handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) throws Exception {
logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
throw e;
}
@ExceptionHandler(Exception.class)
public ResponseEntity<OAuth2Exception> handleException(Exception e) throws Exception {
logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
return getExceptionTranslator().translate(e);
}
@ExceptionHandler(ClientRegistrationException.class)
public ResponseEntity<OAuth2Exception> handleClientRegistrationException(Exception e) throws Exception {
logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
return getExceptionTranslator().translate(new BadClientCredentialsException());
}
@ExceptionHandler(OAuth2Exception.class)
public ResponseEntity<OAuth2Exception> handleException(OAuth2Exception e) throws Exception {
logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
return getExceptionTranslator().translate(e);
}
private WebResponseExceptionTranslator getExceptionTranslator() {
return providerExceptionHandler;
}
}
web.xml 中的更改:只需将 URL 替换为新的
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/user/login</url-pattern>
</servlet-mapping>
最后使用 logincontroller class 创建 bean 并更改 spring-security.xml.
中的 URL
更改 clientCredentialsTokenEndpointFilter 的 oauth 令牌 url 和 url,如下所述。
<sec:http pattern="/user/login" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" use-expressions="true" >
<sec:intercept-url pattern="/user/login" access="isFullyAuthenticated()"/>
<sec:csrf disabled="true"/>
<sec:anonymous enabled="false" />
<sec:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<sec:custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
</sec:http>
<bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<constructor-arg value="/user/login"></constructor-arg>
<property name="authenticationManager" ref="clientAuthenticationManager" />
<property name="filterProcessesUrl" value="/user/login" />
</bean>
<bean class="com.oauth2.provider.endpoint.LoginContrller" />
我正在使用具有 spring 安全性的球衣和 spring-oauth2。我的应用程序在端点“/oauth/token”下运行良好。
我想更改端点以接受更多数据。要求是,我想向令牌 API 发送更多详细信息(即设备详细信息 OS、phone/tablet/web 等)。所以,我想覆盖端点,如果身份验证成功,我想将该额外信息存储在数据库中。
我找不到与以这种方式更改 API 相关的任何内容。 有人可以帮忙吗?
我找到了一个解决方案,方法是编写一个包装器控制器并分配默认的 tokenEndpoint bean
@FrameworkEndpoint
public class LoginContrller{
private static Logger logger = org.slf4j.LoggerFactory.getLogger(LoginContrller.class);
private WebResponseExceptionTranslator providerExceptionHandler = new DefaultWebResponseExceptionTranslator();
@Autowired
private UserManager userManager;
@Autowired
TokenEndpoint tokenEndPoint;
@RequestMapping(value = "/user/login", method=RequestMethod.POST,consumes=MediaType.APPLICATION_JSON)
public ResponseEntity<OAuth2AccessToken> postAccessToken(Principal principal, @RequestParam
Map<String, String> parameters,@RequestBody(required=false) LoginModel loginModel) throws HttpRequestMethodNotSupportedException {
ResponseEntity<OAuth2AccessToken> response = tokenEndPoint.postAccessToken(principal, parameters);
if(!isRefreshTokenRequest(parameters)){
if(loginModel!=null){
loginModel.setUsername(parameters.get("username"));
try {
userManager.loginUser(loginModel);
} catch (UserNotFoundException e) {
logger.warn("Exception in custom login {} ",e);
}
}
}
return response;
}
private boolean isRefreshTokenRequest(Map<String, String> parameters) {
return "refresh_token".equals(parameters.get("grant_type")) && parameters.get("refresh_token") != null;
}
private boolean isAuthCodeRequest(Map<String, String> parameters) {
return "authorization_code".equals(parameters.get("grant_type")) && parameters.get("code") != null;
}
@ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public void handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) throws Exception {
logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
throw e;
}
@ExceptionHandler(Exception.class)
public ResponseEntity<OAuth2Exception> handleException(Exception e) throws Exception {
logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
return getExceptionTranslator().translate(e);
}
@ExceptionHandler(ClientRegistrationException.class)
public ResponseEntity<OAuth2Exception> handleClientRegistrationException(Exception e) throws Exception {
logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
return getExceptionTranslator().translate(new BadClientCredentialsException());
}
@ExceptionHandler(OAuth2Exception.class)
public ResponseEntity<OAuth2Exception> handleException(OAuth2Exception e) throws Exception {
logger.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
return getExceptionTranslator().translate(e);
}
private WebResponseExceptionTranslator getExceptionTranslator() {
return providerExceptionHandler;
}
}
web.xml 中的更改:只需将 URL 替换为新的
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/user/login</url-pattern>
</servlet-mapping>
最后使用 logincontroller class 创建 bean 并更改 spring-security.xml.
中的 URL更改 clientCredentialsTokenEndpointFilter 的 oauth 令牌 url 和 url,如下所述。
<sec:http pattern="/user/login" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" use-expressions="true" >
<sec:intercept-url pattern="/user/login" access="isFullyAuthenticated()"/>
<sec:csrf disabled="true"/>
<sec:anonymous enabled="false" />
<sec:http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<sec:custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
</sec:http>
<bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<constructor-arg value="/user/login"></constructor-arg>
<property name="authenticationManager" ref="clientAuthenticationManager" />
<property name="filterProcessesUrl" value="/user/login" />
</bean>
<bean class="com.oauth2.provider.endpoint.LoginContrller" />