spring boot做OAuth2认证服务端

来源:互联网 发布:深圳索信达数据怎么样 编辑:程序博客网 时间:2024/06/04 20:04

由于公司业务需要,现将在springboot中部署OAuth2服务端的做法记录下来。
OAuth2的流程大致如下:

(A)用户打开客户端以后,客户端要求用户给予授权。(B)用户同意给予客户端授权。(C)客户端使用上一步获得的授权,向认证服务器申请令牌。(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。(E)客户端使用令牌,向资源服务器申请获取资源。(F)资源服务器确认令牌无误,同意向客户端开放资源。

以流程图的形式展现:
这里写图片描述

具体可以参考:OAuth 认证流程详解

引入对应的jar包

<!-- oauth支持 -->        <dependency>            <groupId>org.apache.oltu.oauth2</groupId>            <artifactId>org.apache.oltu.oauth2.authzserver</artifactId>            <version>0.31</version>        </dependency>        <dependency>            <groupId>org.apache.oltu.oauth2</groupId>                           <artifactId>org.apache.oltu.oauth2.resourceserver</artifactId>            <version>0.31</version>        </dependency>

授权获取code

try {            //构建OAuth 授权请求 这里有对应的参数验证            OAuthAuthzRequest oauthRequest = new OAuthAuthzRequest(request);            User user = userService.findByAppId(oauthRequest.getClientId());            // 检查appId是否正确            if (null == user) {                OAuthResponse response = OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)                        .setError(OAuthError.TokenResponse.INVALID_CLIENT)                        .setErrorDescription(Constants.INVALID_CLIENT_DESCRIPTION)                        .buildJSONMessage();                return new ResponseEntity<>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));            }            // 输出请求地址            String url = String.valueOf(request.getRequestURL());            String uri = String.valueOf(request.getRequestURI());            if (StringUtil.isNotEmpty(uri)) {                url = url.substring(0, url.length() - uri.length());            }            if (!user.getUrl().equalsIgnoreCase(url)) {                OAuthResponse response = OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)                        .setError(OAuthError.TokenResponse.INVALID_CLIENT)                        .setErrorDescription(Constants.INVALID_URL_ADDRESS)                        .buildJSONMessage();                return new ResponseEntity<>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));            }            //生成授权码            String authorizationCode;            //responseType目前仅支持CODE,另外还有TOKEN            String responseType = oauthRequest.getParam(OAuth.OAUTH_RESPONSE_TYPE);            if (responseType.equals(ResponseType.CODE.toString())) {                OAuthIssuerImpl oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());                authorizationCode = oauthIssuerImpl.authorizationCode();                oAuthService.addAuthCode(authorizationCode, "aLOCK_DXY");            } else {                OAuthResponse response = OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)                        .setError(OAuthError.TokenResponse.INVALID_CLIENT)                        .setErrorDescription(Constants.INVALID_RESPONSE_TYPE)                        .buildJSONMessage();                return new ResponseEntity<>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));            }            //进行OAuth响应构建            OAuthASResponse.OAuthAuthorizationResponseBuilder builder =                    OAuthASResponse.authorizationResponse(request, HttpServletResponse.SC_FOUND);            //设置授权码            builder.setCode(authorizationCode);            //得到到客户端重定向地址            String redirectURI = oauthRequest.getParam(OAuth.OAUTH_REDIRECT_URI);            //构建响应            final OAuthResponse response = builder.location(redirectURI).buildQueryMessage();            //根据OAuthResponse返回ResponseEntity响应            HttpHeaders headers = new HttpHeaders();            headers.setLocation(new URI(response.getLocationUri()));            return new ResponseEntity(headers, HttpStatus.valueOf(response.getResponseStatus()));        } catch (OAuthProblemException e) {            //出错处理            String redirectUri = e.getRedirectUri();            if (OAuthUtils.isEmpty(redirectUri)) {                //告诉客户端没有传入redirectUri直接报错                return new ResponseEntity<>("OAuth callback url needs to be provided by client!!!", HttpStatus.NOT_FOUND);            }            //返回错误消息(如?error=)            final OAuthResponse response = OAuthASResponse.errorResponse(HttpServletResponse.SC_FOUND).error(e).location(redirectUri).buildQueryMessage();            HttpHeaders headers = new HttpHeaders();            headers.setLocation(new URI(response.getLocationUri()));            return new ResponseEntity(headers, HttpStatus.valueOf(response.getResponseStatus()));        }

根据code获取accessToken

try {            //构建OAuth请求            OAuthTokenRequest oauthRequest = new OAuthTokenRequest(request);            //检查提交的客户端id是否正确            if (null == userService.findByAppId(oauthRequest.getParam("client_id"))) {                OAuthResponse response =                        OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST)                                .setError(OAuthError.TokenResponse.INVALID_CLIENT)                                .setErrorDescription(Constants.INVALID_CLIENT_DESCRIPTION)                                .buildJSONMessage();                return new ResponseEntity<>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));            }            // 检查客户端安全KEY是否正确            if (null == userService.findByAppSecret(oauthRequest.getParam("client_secret"))) {                OAuthResponse response =                        OAuthASResponse.errorResponse(HttpServletResponse.SC_UNAUTHORIZED)                                .setError(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT)                                .setErrorDescription(Constants.INVALID_CLIENT_DESCRIPTION)                                .buildJSONMessage();                return new ResponseEntity<>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));            }            String authCode = oauthRequest.getParam(OAuth.OAUTH_CODE);            // 检查验证类型,此处只检查AUTHORIZATION_CODE类型,其他的还有PASSWORD或REFRESH_TOKEN            if (oauthRequest.getParam(OAuth.OAUTH_GRANT_TYPE).equals(GrantType.AUTHORIZATION_CODE.toString())) {                if (!oAuthService.checkAuthCode(authCode)) {                    OAuthResponse response = OAuthASResponse                            .errorResponse(HttpServletResponse.SC_BAD_REQUEST)                            .setError(OAuthError.TokenResponse.INVALID_GRANT)                            .setErrorDescription("错误的授权码")                            .buildJSONMessage();                    return new ResponseEntity<>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));                }            }            //生成Access Token            OAuthIssuer oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());            final String accessToken = oauthIssuerImpl.accessToken();            final String refreshToken = oauthIssuerImpl.refreshToken();            // oAuthService.addAccessToken(accessToken, oAuthService.getUsernameByAuthCode(authCode));            //生成OAuth响应 2小时过期            OAuthResponse response = OAuthASResponse                    .tokenResponse(HttpServletResponse.SC_OK)                    .setAccessToken(accessToken)                    .setRefreshToken(refreshToken)                    .setExpiresIn(String.valueOf(oAuthService.getExpireIn()))                    .buildJSONMessage();            //根据OAuthResponse生成ResponseEntity            return new ResponseEntity<>(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));        } catch (OAuthProblemException e) {            //构建错误响应            OAuthResponse res = OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST).error(e).buildJSONMessage();            return new ResponseEntity<>(res.getBody(), HttpStatus.valueOf(res.getResponseStatus()));        }

根据accessToken获取用户信息

try {            //构建OAuth资源请求            OAuthAccessResourceRequest oauthRequest = new OAuthAccessResourceRequest(request, ParameterStyle.QUERY);            //获取Access Token            String accessToken = oauthRequest.getAccessToken();            //验证Access Token            if (!oAuthService.checkAccessToken(accessToken)) {                // 如果不存在/过期了,返回未验证错误,需重新验证                OAuthResponse oauthResponse = OAuthRSResponse                        .errorResponse(HttpServletResponse.SC_UNAUTHORIZED)                        .setRealm(Constants.RESOURCE_SERVER_NAME)                        .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);            }            //返回用户名            String username = "aLOCK2";            return new ResponseEntity<>(username, HttpStatus.OK);        } catch (OAuthProblemException e) {            //检查是否设置了错误码            String errorCode = e.getError();            if (OAuthUtils.isEmpty(errorCode)) {                OAuthResponse oauthResponse = OAuthRSResponse                        .errorResponse(HttpServletResponse.SC_UNAUTHORIZED)                        .setRealm(Constants.RESOURCE_SERVER_NAME)                        .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)                    .setRealm(Constants.RESOURCE_SERVER_NAME)                    .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));            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);        }

这里面没有加入刷新机制,感兴趣的可以自己加下。这样一个大致的OAuth2流程就搭起来来了。

原创粉丝点击