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流程就搭起来来了。
阅读全文
1 0
- spring boot做OAuth2认证服务端
- spring boot security oauth2 jwt 服务端实现
- Spring-boot集成Netty做websocket服务端
- Spring Boot OAuth2
- spring-boot oauth2
- Spring boot OAuth2 例子
- Spring Cloud OAuth2 认证流程
- Spring Boot and OAuth2翻译
- 利用Spring Boot Oauth2 来熟悉oauth2 之
- Spring boot --Oauth2.0 + 单点登录
- 使用Spring boot 快速 搭建 OAuth2 Server
- OAuth2认证
- 使用Spring Security和OAuth2实现RESTful服务安全认证
- 使用Spring Security和OAuth2实现RESTful服务安全认证
- Spring Security+OAuth2 + JWT认证以及携带用户信息
- Spring Security和OAuth2实现RESTful服务安全认证
- spring boot security oauth2 实现第三方登录
- spring boot + security oauth2 + redis + mongodb 框架搭建
- 洛谷 P1077 摆花
- git版本管理
- div里写if语句
- 八大算法思想(二)------------------递归算法
- React/React Native 的ES5 ES6写法对照表
- spring boot做OAuth2认证服务端
- 使用RedisDB,封装dll
- 彻底删除 本机上安装的服务程序 ,以删除apache为例子
- JAVA学习之 35-JAVA中的字符串知识点整理(二)
- Linux 自动同步时间
- 9.脚本语言知识总结
- 自从有了BigInteger,我再也不用担心要处理的数据有多大了
- CMarkUp使用简介,XML读取
- 笔记