OAuth2.0授权码模式学习
四种授权方式
1,授权码模式
2,简化模式
3,密码模式
4,客户端模式
授权码模式
四种授权模式中最完成,最严密的授权。
(1)用户访问客户端,后者将前者导入认证服务器
(2)用户选择是否给予客户端授权
(3)假设用户给予授权,认证服务器将用户导向客户端事先指定的“重定向URL”(redirection URL),同时附上一个授权码。
(4)客户端收到授权码,附上早先的“重定向URL”,向认证服务器中申请令牌(assess token)和更新令牌(refresh token)
接入QQ登录的前置条件以及开放平台账号申请
引入官方SDK
--SDK参数配置
--SDK核心方法解读
服务端代码示例:
package com.flash.dataU.oauth.controller2; import com.flash.dataU.oauth.entity.User; import org.apache.oltu.oauth2.as.issuer.MD5Generator; import org.apache.oltu.oauth2.as.issuer.OAuthIssuer; import org.apache.oltu.oauth2.as.issuer.OAuthIssuerImpl; import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest; import org.apache.oltu.oauth2.as.request.OAuthTokenRequest; import org.apache.oltu.oauth2.as.response.OAuthASResponse; import org.apache.oltu.oauth2.common.OAuth; import org.apache.oltu.oauth2.common.exception.OAuthProblemException; import org.apache.oltu.oauth2.common.exception.OAuthSystemException; import org.apache.oltu.oauth2.common.message.OAuthResponse; import org.apache.oltu.oauth2.common.message.types.ParameterStyle; import org.apache.oltu.oauth2.common.utils.OAuthUtils; import org.apache.oltu.oauth2.rs.request.OAuthAccessResourceRequest; import org.apache.oltu.oauth2.rs.response.OAuthRSResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.net.URI; import static org.apache.oltu.oauth2.common.OAuth.*; @RequestMapping("/oauthserver") @Controller public class AuthorizeController { private Model model; private HttpServletRequest request; //向客户端返回授权许可码 code @RequestMapping("/responseCode") public Object toShowUser(Model model, HttpServletRequest request){ this.model = model; this.request = request; System.out.println("----------服务端/responseCode--------------------------------------------------------------"); try { //构建OAuth授权请求 OAuthAuthzRequest oauthRequest =new OAuthAuthzRequest(request); /*oauthRequest.getClientId(); oauthRequest.getResponseType(); oauthRequest.getRedirectURI(); System.out.println(oauthRequest.getClientId()); System.out.println(oauthRequest.getResponseType()); System.out.println(oauthRequest.getRedirectURI());*/ if(oauthRequest.getClientId()!=null&&oauthRequest.getClientId()!="") { //设置授权码 String authorizationCode ="authorizationCode"; //利用oauth授权请求设置responseType,目前仅支持CODE,另外还有TOKEN String responseType =oauthRequest.getParam(OAuth.OAUTH_RESPONSE_TYPE); //进行OAuth响应构建 OAuthASResponse.OAuthAuthorizationResponseBuilder builder = OAuthASResponse.authorizationResponse(request, HttpServletResponse.SC_FOUND); //设置授权码 builder.setCode(authorizationCode); //得到到客户端重定向地址 String redirectURI =oauthRequest.getParam(OAUTH_REDIRECT_URI); //构建响应 final OAuthResponse response =builder.location(redirectURI).buildQueryMessage(); System.out.println("服务端/responseCode内,返回的回调路径:"+response.getLocationUri()); System.out.println("----------服务端/responseCode--------------------------------------------------------------"); String responceUri =response.getLocationUri(); //根据OAuthResponse返回ResponseEntity响应 HttpHeaders headers =new HttpHeaders(); try { headers.setLocation(new URI(response.getLocationUri())); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return"redirect:"+responceUri; } } catch (Exception e) { e.printStackTrace(); } System.out.println("----------服务端/responseCode--------------------------------------------------------------"); return null; } //获取客户端的code码,向客户端返回access token @RequestMapping(value="/responseAccessToken",method = RequestMethod.POST) public HttpEntity token(HttpServletRequest request){ System.out.println("--------服务端/responseAccessToken-----------------------------------------------------------"); OAuthIssuer oauthIssuerImpl=null; OAuthResponse response=null; //构建OAuth请求 try { OAuthTokenRequest oauthRequest =new OAuthTokenRequest(request); String authCode =oauthRequest.getParam(OAuth.OAUTH_CODE); String clientSecret = oauthRequest.getClientSecret(); if(clientSecret!=null||clientSecret!=""){ //生成Access Token oauthIssuerImpl =new OAuthIssuerImpl(new MD5Generator()); final String accessToken =oauthIssuerImpl.accessToken(); System.out.println(accessToken); System.out.println("--oooo---"); //生成OAuth响应 response = OAuthASResponse .tokenResponse(HttpServletResponse.SC_OK) .setAccessToken(accessToken) .buildJSONMessage(); } System.out.println("--------服务端/responseAccessToken-----------------------------------------------------------"); //根据OAuthResponse生成ResponseEntity return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus())); } catch (OAuthSystemException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (OAuthProblemException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("--------服务端/responseAccessToken-----------------------------------------------------------"); return null; } // 向客户端返回请求资源(username)的controller方法 @RequestMapping("/userInfo") public HttpEntity userInfo(HttpServletRequest request)throws OAuthSystemException{ System.out.println("-----------服务端/userInfo-------------------------------------------------------------"); try { //获取客户端传来的OAuth资源请求 OAuthAccessResourceRequest oauthRequest =new OAuthAccessResourceRequest(request, ParameterStyle.QUERY); //获取Access Token String accessToken =oauthRequest.getAccessToken(); System.out.println("accessToken"); //验证Access Token /*if (accessToken==null||accessToken=="") { // 如果不存在/过期了,返回未验证错误,需重新验证 OAuthResponse oauthResponse = OAuthRSResponse .errorResponse(HttpServletResponse.SC_UNAUTHORIZED) .setError(OAuthError.ResourceResponse.INVALID_TOKEN) .buildHeaderMessage(); HttpHeaders headers = new HttpHeaders(); headers.add(OAuth.HeaderType.WWW_AUTHENTICATE, oauthResponse.getHeader(OAuth.HeaderType.WWW_AUTHENTICATE)); return new ResponseEntity(headers, HttpStatus.UNAUTHORIZED); } */ //返回用户名 User user=new User("小明"); String username = accessToken+"---"+Math.random()+"----"+user.getUsername(); System.out.println(username); System.out.println("服务端/userInfo::::::ppp"); System.out.println("-----------服务端/userInfo----------------------------------------------------------"); return new ResponseEntity(username, HttpStatus.OK); } catch (OAuthProblemException e) { // TODO Auto-generated catch block e.printStackTrace(); //检查是否设置了错误码 String errorCode =e.getError(); if (OAuthUtils.isEmpty(errorCode)) { OAuthResponse oauthResponse = OAuthRSResponse .errorResponse(HttpServletResponse.SC_UNAUTHORIZED) .buildHeaderMessage(); HttpHeaders headers =new HttpHeaders(); headers.add(OAuth.HeaderType.WWW_AUTHENTICATE, oauthResponse.getHeader(OAuth.HeaderType.WWW_AUTHENTICATE)); return new ResponseEntity(headers, HttpStatus.UNAUTHORIZED); } OAuthResponse oauthResponse = OAuthRSResponse .errorResponse(HttpServletResponse.SC_UNAUTHORIZED) .setError(e.getError()) .setErrorDescription(e.getDescription()) .setErrorUri(e.getUri()) .buildHeaderMessage(); HttpHeaders headers =new HttpHeaders(); headers.add(OAuth.HeaderType.WWW_AUTHENTICATE, oauthResponse.getHeader(OAuth.HeaderType.WWW_AUTHENTICATE)); System.out.println("-----------服务端/userInfo------------------------------------------------------------------------------"); return new ResponseEntity(HttpStatus.BAD_REQUEST); } } }
客户端代码示例:
package com.flash.dataU.oauth.controller2; import org.apache.oltu.oauth2.client.OAuthClient; import org.apache.oltu.oauth2.client.URLConnectionClient; import org.apache.oltu.oauth2.client.request.OAuthBearerClientRequest; import org.apache.oltu.oauth2.client.request.OAuthClientRequest; import org.apache.oltu.oauth2.client.response.OAuthAccessTokenResponse; import org.apache.oltu.oauth2.client.response.OAuthResourceResponse; import org.apache.oltu.oauth2.common.OAuth; import org.apache.oltu.oauth2.common.exception.OAuthProblemException; import org.apache.oltu.oauth2.common.exception.OAuthSystemException; import org.apache.oltu.oauth2.common.message.types.GrantType; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; //接受客户端返回的code,提交申请access token的请求 @RequestMapping("/server") @Controller public class ServerController { String clientId = null; String clientSecret = null; String accessTokenUrl = null; String userInfoUrl = null; String redirectUrl = null; String response_type = null; String code= null; //提交申请code的请求 @RequestMapping("/requestServerCode") public String requestServerFirst() { clientId = "clientId"; clientSecret = "clientSecret"; accessTokenUrl = "responseCode"; redirectUrl = "http://localhost:8081/server/callbackCode"; response_type = "code"; OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient()); String requestUrl = null; try { //构建oauthd的请求。设置请求服务地址(accessTokenUrl)、clientId、response_type、redirectUrl OAuthClientRequest accessTokenRequest = OAuthClientRequest .authorizationLocation(accessTokenUrl) .setResponseType(response_type) .setClientId(clientId) .setRedirectURI(redirectUrl) .buildQueryMessage(); requestUrl = accessTokenRequest.getLocationUri(); System.out.println(requestUrl); } catch (Exception e) { e.printStackTrace(); } System.out.println(requestUrl); return "redirect:http://localhost:8080/oauthserver/" + requestUrl; } //接受客户端返回的code,提交申请access token的请求 @RequestMapping("/callbackCode") public Object toLogin(HttpServletRequest request)throws OAuthProblemException{ System.out.println("-----------客户端/callbackCode--------------------------------------------------------------------------------"); clientId = "clientId"; clientSecret = "clientSecret"; accessTokenUrl="http://localhost:8080/oauthserver/responseAccessToken"; userInfoUrl = "userInfoUrl"; redirectUrl = "http://localhost:8081/server/accessToken"; HttpServletRequest httpRequest = (HttpServletRequest)request; code = httpRequest.getParameter("code"); System.out.println(code); OAuthClient oAuthClient =new OAuthClient(new URLConnectionClient()); try { OAuthClientRequest accessTokenRequest = OAuthClientRequest .tokenLocation(accessTokenUrl) .setGrantType(GrantType.AUTHORIZATION_CODE) .setClientId(clientId) .setClientSecret(clientSecret) .setCode(code) .setRedirectURI(redirectUrl) .buildQueryMessage(); //去服务端请求access token,并返回响应 OAuthAccessTokenResponse oAuthResponse =oAuthClient.accessToken(accessTokenRequest, OAuth.HttpMethod.POST); //获取服务端返回过来的access token String accessToken = oAuthResponse.getAccessToken(); //查看access token是否过期 Long expiresIn =oAuthResponse.getExpiresIn(); System.out.println("客户端/callbackCode方法的token:::"+accessToken); System.out.println("-----------客户端/callbackCode--------------------------------------------------------------------------------"); return"redirect:http://localhost:8081/server/accessToken?accessToken="+accessToken; } catch (OAuthSystemException e) { e.printStackTrace(); } return null; } //接受服务端传回来的access token,由此token去请求服务端的资源(用户信息等) @RequestMapping("/accessToken") public ModelAndView accessToken(String accessToken ) { System.out.println("---------客户端/accessToken----------------------------------------------------------------------------------"); userInfoUrl = "http://localhost:8080/oauthserver/userInfo"; System.out.println("accessToken"); OAuthClient oAuthClient =new OAuthClient(new URLConnectionClient()); try { OAuthClientRequest userInfoRequest =new OAuthBearerClientRequest(userInfoUrl) .setAccessToken(accessToken).buildQueryMessage(); OAuthResourceResponse resourceResponse =oAuthClient.resource(userInfoRequest, OAuth.HttpMethod.GET, OAuthResourceResponse.class); String username = resourceResponse.getBody(); System.out.println(username); ModelAndView modelAndView =new ModelAndView("usernamePage"); modelAndView.addObject("username",username); System.out.println("---------客户端/accessToken----------------------------------------------------------------------------------"); return modelAndView; } catch (Exception e) { e.printStackTrace(); } System.out.println("---------客户端/accessToken----------------------------------------------------------------------------------"); return null; } }