parent
f6842744df
commit
29208d8479
|
@ -37,6 +37,24 @@ http://localhost:8080/spring-oauth-server/unity/dashboard.htm?access_token=3420d
|
||||||
http://localhost:8080/spring-oauth-server/oauth/token?client_id=mobile-client&client_secret=mobile&grant_type=refresh_token&refresh_token=b36f4978-a172-4aa8-af89-60f58abe3ba1
|
http://localhost:8080/spring-oauth-server/oauth/token?client_id=mobile-client&client_secret=mobile&grant_type=refresh_token&refresh_token=b36f4978-a172-4aa8-af89-60f58abe3ba1
|
||||||
|
|
||||||
|
|
||||||
|
Restful OAuth2 Test [POST]
|
||||||
|
URL: /oauth2/rest_token
|
||||||
|
ContentType: application/json
|
||||||
|
|
||||||
|
DEMO URL: http://localhost:8080/spring-oauth-server/oauth2/rest_token
|
||||||
|
Request Body: {"grant_type":"client_credentials","scope":"read","client_id":"credentials","client_secret":"credentials","username":"user","password":"123"}
|
||||||
|
|
||||||
|
Response Body:
|
||||||
|
{
|
||||||
|
"access_token": "cd165ebc-562d-45df-8488-9f1ba947553e",
|
||||||
|
"token_type": "bearer",
|
||||||
|
"expires_in": 43193,
|
||||||
|
"scope": "read"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
更多的测试请访问
|
更多的测试请访问
|
||||||
http://git.oschina.net/mkk/spring-oauth-client
|
http://git.oschina.net/mkk/spring-oauth-client
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,206 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015 MONKEYK Information Technology Co. Ltd
|
||||||
|
* www.monkeyk.com
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This software is the confidential and proprietary information of
|
||||||
|
* MONKEYK Information Technology Co. Ltd ("Confidential Information").
|
||||||
|
* You shall not disclose such Confidential Information and shall use
|
||||||
|
* it only in accordance with the terms of the license agreement you
|
||||||
|
* entered into with MONKEYK Information Technology Co. Ltd.
|
||||||
|
*/
|
||||||
|
package com.monkeyk.sos.web.controller;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||||
|
import org.springframework.security.oauth2.common.exceptions.*;
|
||||||
|
import org.springframework.security.oauth2.common.util.OAuth2Utils;
|
||||||
|
import org.springframework.security.oauth2.provider.*;
|
||||||
|
import org.springframework.security.oauth2.provider.client.ClientCredentialsTokenGranter;
|
||||||
|
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
|
||||||
|
import org.springframework.security.oauth2.provider.code.AuthorizationCodeTokenGranter;
|
||||||
|
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
|
||||||
|
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
|
||||||
|
import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter;
|
||||||
|
import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
|
||||||
|
import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter;
|
||||||
|
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
|
||||||
|
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestValidator;
|
||||||
|
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 2016/3/8
|
||||||
|
* <p/>
|
||||||
|
* Restful OAuth API
|
||||||
|
*
|
||||||
|
* @author Shengzhao Li
|
||||||
|
* @see org.springframework.security.oauth2.provider.endpoint.TokenEndpoint
|
||||||
|
*/
|
||||||
|
@Controller
|
||||||
|
public class OAuthRestController implements InitializingBean, ApplicationContextAware {
|
||||||
|
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(OAuthRestController.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ClientDetailsService clientDetailsService;
|
||||||
|
@Autowired
|
||||||
|
private AuthorizationServerTokenServices tokenServices;
|
||||||
|
@Autowired
|
||||||
|
private AuthorizationCodeServices authorizationCodeServices;
|
||||||
|
|
||||||
|
private AuthenticationManager authenticationManager;
|
||||||
|
|
||||||
|
private OAuth2RequestFactory oAuth2RequestFactory;
|
||||||
|
|
||||||
|
private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator();
|
||||||
|
private WebResponseExceptionTranslator providerExceptionHandler = new DefaultWebResponseExceptionTranslator();
|
||||||
|
|
||||||
|
|
||||||
|
@RequestMapping(value = "/oauth2/rest_token", method = RequestMethod.POST)
|
||||||
|
@ResponseBody
|
||||||
|
public OAuth2AccessToken postAccessToken(@RequestBody Map<String, String> parameters) {
|
||||||
|
|
||||||
|
|
||||||
|
String clientId = getClientId(parameters);
|
||||||
|
ClientDetails authenticatedClient = clientDetailsService.loadClientByClientId(clientId);
|
||||||
|
|
||||||
|
TokenRequest tokenRequest = oAuth2RequestFactory.createTokenRequest(parameters, authenticatedClient);
|
||||||
|
|
||||||
|
if (clientId != null && !clientId.equals("")) {
|
||||||
|
// Only validate the client details if a client authenticated during this
|
||||||
|
// request.
|
||||||
|
if (!clientId.equals(tokenRequest.getClientId())) {
|
||||||
|
// double check to make sure that the client ID in the token request is the same as that in the
|
||||||
|
// authenticated client
|
||||||
|
throw new InvalidClientException("Given client ID does not match authenticated client");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authenticatedClient != null) {
|
||||||
|
oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String grantType = tokenRequest.getGrantType();
|
||||||
|
if (!StringUtils.hasText(grantType)) {
|
||||||
|
throw new InvalidRequestException("Missing grant type");
|
||||||
|
}
|
||||||
|
if (grantType.equals("implicit")) {
|
||||||
|
throw new InvalidGrantException("Implicit grant type not supported from token endpoint");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAuthCodeRequest(parameters)) {
|
||||||
|
// The scope was requested or determined during the authorization step
|
||||||
|
if (!tokenRequest.getScope().isEmpty()) {
|
||||||
|
LOG.debug("Clearing scope of incoming token request");
|
||||||
|
tokenRequest.setScope(Collections.<String>emptySet());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (isRefreshTokenRequest(parameters)) {
|
||||||
|
// A refresh token has its own default scopes, so we should ignore any added by the factory here.
|
||||||
|
tokenRequest.setScope(OAuth2Utils.parseParameterList(parameters.get(OAuth2Utils.SCOPE)));
|
||||||
|
}
|
||||||
|
|
||||||
|
OAuth2AccessToken token = getTokenGranter(grantType).grant(grantType, tokenRequest);
|
||||||
|
if (token == null) {
|
||||||
|
throw new UnsupportedGrantTypeException("Unsupported grant type: " + grantType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return token;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TokenGranter getTokenGranter(String grantType) {
|
||||||
|
|
||||||
|
if ("authorization_code".equals(grantType)) {
|
||||||
|
return new AuthorizationCodeTokenGranter(tokenServices, authorizationCodeServices, clientDetailsService, this.oAuth2RequestFactory);
|
||||||
|
} else if ("password".equals(grantType)) {
|
||||||
|
return new ResourceOwnerPasswordTokenGranter(getAuthenticationManager(), tokenServices, clientDetailsService, this.oAuth2RequestFactory);
|
||||||
|
} else if ("refresh_token".equals(grantType)) {
|
||||||
|
return new RefreshTokenGranter(tokenServices, clientDetailsService, this.oAuth2RequestFactory);
|
||||||
|
} else if ("client_credentials".equals(grantType)) {
|
||||||
|
return new ClientCredentialsTokenGranter(tokenServices, clientDetailsService, this.oAuth2RequestFactory);
|
||||||
|
} else if ("implicit".equals(grantType)) {
|
||||||
|
return new ImplicitTokenGranter(tokenServices, clientDetailsService, this.oAuth2RequestFactory);
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedGrantTypeException("Unsupport grant_type: " + grantType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
public ResponseEntity<OAuth2Exception> handleException(Exception e) throws Exception {
|
||||||
|
LOG.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
|
||||||
|
return getExceptionTranslator().translate(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(ClientRegistrationException.class)
|
||||||
|
public ResponseEntity<OAuth2Exception> handleClientRegistrationException(Exception e) throws Exception {
|
||||||
|
LOG.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
|
||||||
|
return getExceptionTranslator().translate(new BadClientCredentialsException());
|
||||||
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(OAuth2Exception.class)
|
||||||
|
public ResponseEntity<OAuth2Exception> handleException(OAuth2Exception e) throws Exception {
|
||||||
|
LOG.info("Handling error: " + e.getClass().getSimpleName() + ", " + e.getMessage());
|
||||||
|
return getExceptionTranslator().translate(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected String getClientId(Map<String, String> parameters) {
|
||||||
|
return parameters.get("client_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuthenticationManager getAuthenticationManager() {
|
||||||
|
return this.authenticationManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
|
||||||
|
Assert.state(clientDetailsService != null, "ClientDetailsService must be provided");
|
||||||
|
Assert.state(authenticationManager != null, "AuthenticationManager must be provided");
|
||||||
|
|
||||||
|
oAuth2RequestFactory = new DefaultOAuth2RequestFactory(clientDetailsService);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected WebResponseExceptionTranslator getExceptionTranslator() {
|
||||||
|
return providerExceptionHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
|
if (this.authenticationManager == null) {
|
||||||
|
this.authenticationManager = (AuthenticationManager) applicationContext.getBean("authenticationManager");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,7 +29,7 @@
|
||||||
<div>
|
<div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<p class="text-center text-muted">
|
<p class="text-center text-muted">
|
||||||
© 2013 - 2015
|
© 2013 - 2016
|
||||||
<a href="mailto:sz@monkeyk.com">sz@monkeyk.com</a> from <a
|
<a href="mailto:sz@monkeyk.com">sz@monkeyk.com</a> from <a
|
||||||
href="http://git.oschina.net/shengzhao/spring-oauth-server" target="_blank">spring-oauth-server</a>
|
href="http://git.oschina.net/shengzhao/spring-oauth-server" target="_blank">spring-oauth-server</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
|
@ -13,5 +13,10 @@
|
||||||
<a href="../">Home</a>
|
<a href="../">Home</a>
|
||||||
|
|
||||||
<h2>Hi Mobile.</h2>
|
<h2>Hi Mobile.</h2>
|
||||||
|
|
||||||
|
Principal: <strong>${SPRING_SECURITY_CONTEXT.authentication.principal}</strong>
|
||||||
|
<br/>
|
||||||
|
<a href="${contextPath}/logout.do">Logout</a>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -13,5 +13,10 @@
|
||||||
<a href="../">Home</a>
|
<a href="../">Home</a>
|
||||||
|
|
||||||
<h2>Hi Unity.</h2>
|
<h2>Hi Unity.</h2>
|
||||||
|
|
||||||
|
Principal: <strong>${SPRING_SECURITY_CONTEXT.authentication.principal}</strong>
|
||||||
|
<br/>
|
||||||
|
<a href="${contextPath}/logout.do">Logout</a>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -4,15 +4,20 @@
|
||||||
--%>
|
--%>
|
||||||
|
|
||||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
||||||
|
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
|
||||||
<!DOCTYPE HTML>
|
<!DOCTYPE HTML>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Home</title>
|
<title>Home</title>
|
||||||
|
<c:set var="contextPath" value="${pageContext.request.contextPath}" scope="application"/>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h2>Spring Security&Oauth2 is work!</h2>
|
<h2>Spring Security&Oauth2 is work!</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
<a href="${contextPath}/login.jsp">Login</a>
|
||||||
|
|
|
||||||
<a href="${contextPath}/logout.do">Logout</a>
|
<a href="${contextPath}/logout.do">Logout</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
@ -21,7 +26,7 @@
|
||||||
<ol>
|
<ol>
|
||||||
<li>
|
<li>
|
||||||
<p>
|
<p>
|
||||||
菜单 User 是不需要Oauth 验证即可访问的(即公开的resource)
|
菜单 User 是不需要Oauth 验证即可访问的(即公开的resource); 用于管理用户信息(添加,删除等).
|
||||||
</p>
|
</p>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
Loading…
Reference in New Issue