oauth简单使用

一、oauth原理参考

  理解OAuth 2.0

二、本例中采用授权码模式

  

  大致流程

  (A)用户访问客户端,后者将前者导向认证服务器。
  (B)用户选择是否给予客户端授权。
  (C)假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。
  (D)客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
  (E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。

  参数含义

  response_type:表示授权类型,必选项,此处的值固定为"code"
  client_id:表示客户端的ID,必选项
  redirect_uri:表示重定向URI,可选项
  scope:表示申请的权限范围,可选项,本例中无
  state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值,本例中无

三、项目中依赖oauth相关jar

<!-- oauth -->
<dependency><groupId>org.apache.oltu.oauth2</groupId><artifactId>org.apache.oltu.oauth2.resourceserver</artifactId><version>${oauth2-version}</version>
</dependency>
<dependency><groupId>org.apache.oltu.oauth2</groupId><artifactId>org.apache.oltu.oauth2.authzserver</artifactId><version>${oauth2-version}</version>
</dependency>
<dependency><groupId>org.apache.oltu.oauth2</groupId><artifactId>org.apache.oltu.oauth2.client</artifactId><version>${oauth2-version}</version>
</dependency>

四、获取授权码

/*** 获取授权码-服务端** @param request* @return* @throws OAuthProblemException* @throws OAuthSystemException*/
@RequestMapping(value = "/authorize", method = RequestMethod.GET)
@ResponseBody
public Object authorize(HttpServletRequest request) throws URISyntaxException, OAuthProblemException, OAuthSystemException {try {// 构建OAuth授权请求OAuthAuthzRequest oauthRequest = new OAuthAuthzRequest(request);// 1.获取OAuth客户端idString clientId = oauthRequest.getClientId();// 校验客户端id是否正确LightUserResult lightUserResult = userApi.queryUserByClientId(clientId);if (null == lightUserResult) {OAuthResponse response =OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST).setError(OAuthError.TokenResponse.INVALID_CLIENT).setErrorDescription("无效的客户端ID").buildJSONMessage();return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));}// 2.生成授权码String authCode = null;String responseType = oauthRequest.getParam(OAuth.OAUTH_RESPONSE_TYPE);// ResponseType仅支持CODE和TOKENif (responseType.equals(ResponseType.CODE.toString())) {OAuthIssuerImpl oAuthIssuer = new OAuthIssuerImpl(new MD5Generator());authCode = oAuthIssuer.authorizationCode();// 存入缓存中authCode-username
            RedisUtil.getRedis().set(authCode, lightUserResult.getUserName());}return new ResponseEntity(authCode, HttpStatus.OK);} catch (Exception e) {return new ResponseEntity("内部错误", HttpStatus.valueOf(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));}
}

五、根据授权码获取token

/*** 获取访问令牌** @param request* @return* @throws OAuthProblemException* @throws OAuthSystemException*/
@RequestMapping(value = "accessToken", method = RequestMethod.POST)
@ResponseBody
public Object accessToken(HttpServletRequest request) throws OAuthProblemException, OAuthSystemException {try {// 构建OAuth请求OAuthTokenRequest tokenRequest = new OAuthTokenRequest(request);// 1.获取OAuth客户端idString clientId = tokenRequest.getClientId();// 校验客户端id是否正确LightUserResult lightUserResult = userApi.queryUserByClientId(clientId);if (null == lightUserResult) {OAuthResponse oAuthResponse = OAuthResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST).setError(OAuthError.TokenResponse.INVALID_CLIENT).setErrorDescription("无效的客户端ID").buildJSONMessage();return new ResponseEntity(oAuthResponse.getBody(), HttpStatus.valueOf(oAuthResponse.getResponseStatus()));}// 2.检查客户端安全key是否正确if (!lightUserResult.getClientSecret().equals(tokenRequest.getClientSecret())) {OAuthResponse oAuthResponse = OAuthResponse.errorResponse(HttpServletResponse.SC_UNAUTHORIZED).setError(OAuthError.TokenResponse.UNAUTHORIZED_CLIENT).setErrorDescription("客户端安全key认证不通过").buildJSONMessage();return new ResponseEntity<>(oAuthResponse.getBody(), HttpStatus.valueOf(oAuthResponse.getResponseStatus()));}// 3.检查授权码是否正确String authCode = tokenRequest.getParam(OAuth.OAUTH_CODE);// 检查验证类型,此处只检查AUTHORIZATION_CODE类型,其他的还有password或REFRESH_TOKENif (!tokenRequest.getParam(OAuth.OAUTH_GRANT_TYPE).equals(GrantType.AUTHORIZATION_CODE.toString())) {if (null == RedisUtil.getRedis().get(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()));}}// 4.生成访问令牌Access TokenOAuthIssuer oAuthIssuer = new OAuthIssuerImpl(new MD5Generator());final String accessToken = oAuthIssuer.accessToken();// 将访问令牌加入缓存:accessToken-username
        RedisUtil.getRedis().set(accessToken, lightUserResult.getUserName());// 5.生成OAuth响应OAuthResponse response = OAuthASResponse.tokenResponse(HttpServletResponse.SC_OK).setAccessToken(accessToken).setExpiresIn(expiresIn).buildJSONMessage();return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));} catch (Exception e) {e.printStackTrace();return new ResponseEntity("内部错误", HttpStatus.valueOf(HttpServletResponse.SC_INTERNAL_SERVER_ERROR));}}

 六、简单测试

@RequestMapping("authority")
@ResponseBody
public JSONObject authority() throws OAuthSystemException, OAuthProblemException {JSONObject result = new JSONObject();OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());OAuthClientRequest codeTokenRequest = OAuthClientRequest.authorizationLocation("http://127.0.0.1:8080/auth-web/oauth/authorize").setResponseType(ResponseType.CODE.toString()).setClientId("c1ebe466-1cdc-4bd3-ab69-77c3561b9dee").buildQueryMessage();//获取 codeOAuthResourceResponse codeResponse = oAuthClient.resource(codeTokenRequest, OAuth.HttpMethod.GET, OAuthResourceResponse.class);if(codeResponse.getResponseCode() != HttpServletResponse.SC_OK) {result.put("code", codeResponse.getResponseCode());result.put("msg", codeResponse.getBody());} else {String authCode = codeResponse.getBody();OAuthClientRequest accessTokenRequest = OAuthClientRequest.tokenLocation("http://127.0.0.1:8080/auth-web/oauth/accessToken").setGrantType(GrantType.AUTHORIZATION_CODE).setClientId("c1ebe466-1cdc-4bd3-ab69-77c3561b9dee").setClientSecret("d8346ea2-6017-43ed-ad68-19c0f971738b").setCode(authCode).setRedirectURI("http://127.0.0.1:8080/auth-web/").buildQueryMessage();//获取access tokenOAuthAccessTokenResponse tokenResponse =oAuthClient.accessToken(accessTokenRequest, OAuth.HttpMethod.POST);if(tokenResponse.getResponseCode() != HttpServletResponse.SC_OK) {result.put("code", tokenResponse.getResponseCode());result.put("msg", tokenResponse.getBody());return result;} else {//验证tokenOAuthClientRequest validateRequest =new OAuthBearerClientRequest("http://127.0.0.1:8080/auth-web/oauth/validate").setAccessToken(tokenResponse.getAccessToken()).buildQueryMessage();OAuthResourceResponse validateResponse = oAuthClient.resource(validateRequest, OAuth.HttpMethod.GET, OAuthResourceResponse.class);if(validateResponse.getResponseCode() != HttpServletResponse.SC_OK) {result.put("code", validateResponse.getResponseCode());result.put("msg", validateResponse.getBody());} else {JSONObject body = JSON.parseObject(validateResponse.getBody());result.put("code", body.getString("code"));result.put("msg", body.getString("msg"));}}}return result;
}
public static ResponseEntity oauthValidate(HttpServletRequest request) throws OAuthProblemException, OAuthSystemException {// 构建OAuth资源请求OAuthAccessResourceRequest resourceRequest = new OAuthAccessResourceRequest(request, ParameterStyle.QUERY);// 获取访问令牌access TokenString accessToken = resourceRequest.getAccessToken();// 验证访问令牌if (null == RedisUtil.getRedis().get(accessToken)) {// 如果不存在或过期了,返回未验证错误,需重新验证OAuthResponse response = OAuthRSResponse.errorResponse(HttpServletResponse.SC_UNAUTHORIZED).setError(OAuthError.ResourceResponse.INVALID_TOKEN).setErrorDescription("访问令牌不存在或已过期,请重新验证").buildJSONMessage();return new ResponseEntity(response.getBody(), HttpStatus.valueOf(response.getResponseStatus()));}return new ResponseEntity("验证成功", HttpStatus.valueOf(HttpServletResponse.SC_OK));
}

七、项目地址

  oauth认证demo下载

转载于:https://www.cnblogs.com/hujunzheng/p/7126766.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/531250.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我眼中的服务提供和服务消费

服务提供和消费脑图 服务提供和消费脑图 参见: 服务提供者, 服务消费者, 服务注册中心 服务提供者 1.服务提供者启动&#xff0c;解析xml文件中配置的服务&#xff0c;这里使用Dom4j解析。 2.将服务的一些相关信息注册到 服务注册中心。 注&#xff1a;服务相关信息&#xff1a…

shiro整合oauth

前言 如果oauth原理还不清楚的地方&#xff0c;其参考这里。 一、基本思路脑图 二、客户端shiro配置 shiro配置文件 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:util&q…

springmvc+swagger2

一、swagger2依赖 <!--swagger--> <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><exclusions><exclusion><artifactId>spring-aop</artifactId><groupId>org.s…

获取资源文件工具类

如果没有依赖spring&#xff0c;可以将分割线下的方法去掉 import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframe…

无状态shiro认证组件(禁用默认session)

准备内容 简单的shiro无状态认证 无状态认证拦截器 import com.hjzgg.stateless.shiroSimpleWeb.Constants; import com.hjzgg.stateless.shiroSimpleWeb.realm.StatelessToken; import org.apache.shiro.web.filter.AccessControlFilter;import javax.servlet.ServletRequest;…

Spring根据包名获取包路径下的所有类

参考mybatis MapperScannerConfigurer.java 最终找到 Spring的一个类 ClassPathBeanDefinitionScanner.java 参考ClassPathBeanDefinitionScanner 和它的父类 ClassPathScanningCandidateComponentProvider&#xff0c;将一些代码进行抽取&#xff0c;得到如下工具类。 import…

idea模板注释

类文件头部的注释 #if (${PACKAGE_NAME} && ${PACKAGE_NAME} ! "")package ${PACKAGE_NAME};#end #parse("File Header.java") /** * ${DESCRIPTION} * author ${USER} hujunzheng * create ${YEAR}-${MONTH}-${DAY} ${TIME} **/ public class ${N…

redis分布式锁小试

一、场景 项目A监听mq中的其他项目的部署消息&#xff08;包括push_seq, status, environment&#xff0c;timestamp等&#xff09;&#xff0c;然后将部署消息同步到数据库中&#xff08;项目X在对应环境[environment]上部署的push_seq[项目X的版本]&#xff09;。那么问题来了…

Jackson ObjectMapper readValue过程

1.整体调用栈 2.看一下调用栈的两个方法 resolve 方法中通过 Iterator i$ this._beanProperties.iterator() 遍历属性的所有子属性&#xff0c;缓存对应的 deserializer。观察调用栈的方法&#xff0c;可以发现是循环调用的。 3.比如寻找自定义的 LocalDateTime类的序列化实现…

java如何寻找main函数对应的类

参考springboot Class<?> deduceMainApplicationClass() {try {StackTraceElement[] stackTrace new RuntimeException().getStackTrace();for (StackTraceElement stackTraceElement : stackTrace) {if ("main".equals(stackTraceElement.getMethodName())…

jooq实践

用法 sql语句 SELECT AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, COUNT(*)FROM AUTHORJOIN BOOK ON AUTHOR.ID BOOK.AUTHOR_IDWHERE BOOK.LANGUAGE DEAND BOOK.PUBLISHED > DATE 2008-01-01 GROUP BY AUTHOR.FIRST_NAME, AUTHOR.LAST_NAMEHAVING COUNT(*) > 5 ORDER BY AUT…

git根据用户过滤提交记录

使用SourceTree 使用gitk 转载于:https://www.cnblogs.com/hujunzheng/p/8398203.html

cglib动态代理导致注解丢失问题及如何修改注解允许被继承

现象 SOAService这个bean先后经过两个BeanPostProcessor&#xff0c;会发现代理之后注解就丢失了。 开启了cglib代理 SpringBootApplication EnableAspectJAutoProxy(proxyTargetClass true) public class Application {public static void main(String[] args) {SpringApplic…

spring AbstractBeanDefinition创建bean类型是动态代理类的方式

1.接口 Class<?> resourceClass 2.获取builder BeanDefinitionBuilder builder BeanDefinitionBuilder.genericBeanDefinition(resourceClass); 3.获取接口对应的动态代理class Class<?> targetProxyClass Proxy.getProxyClass(XXX.class.getClassLoader(), ne…

微信小程序:一起玩连线,一个算法来搞定

微信小程序&#xff1a;一起玩连线 游戏玩法 将相同颜色的结点连接在一起&#xff0c;连线之间不能交叉。 算法思想 转换为多个源点到达对应终点的路径问题&#xff0c;且路径之间不相交。按照dfs方式寻找两个结点路径&#xff0c;一条路径探索完之后&#xff0c;标记地图并记录…

IntelliJ IDEA关于logger的live template配置

1.安装 log support2插件 2.配置log support2 由于项目中的日志框架是公司自己封装的&#xff0c;所以还需要自己手动改一下 log support2插件生成的live template 当然也可以修改 Log support global的配置 包括 Logger Field、Logger class、Logger Factory class都可以修改。…

springboot项目接入配置中心,实现@ConfigurationProperties的bean属性刷新方案

前言 配置中心&#xff0c;通过keyvalue的形式存储环境变量。配置中心的属性做了修改&#xff0c;项目中可以通过配置中心的依赖&#xff08;sdk&#xff09;立即感知到。需要做的就是如何在属性发生变化时&#xff0c;改变带有ConfigurationProperties的bean的相关属性。 配置…

简单封装kafka相关的api

一、针对于kafka版本 <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>0.8.2.2</version></dependency><dependency><groupId>org.apache.kafka</groupId>…

springmvc controller动态设置content-type

springmvc RequestMappingHandlerAdapter#invokeHandlerMethod 通过ServletInvocableHandlerMethod#invokeAndHandle调用目标方法&#xff0c;并处理返回值。 如果return value &#xff01; null&#xff0c;则通过returnvalueHandlers处理&#xff0c;内部会调用MessageConv…

springboot2.0 redis EnableCaching的配置和使用

一、前言 关于EnableCaching最简单使用&#xff0c;个人感觉只需提供一个CacheManager的一个实例就好了。springboot为我们提供了cache相关的自动配置。引入cache模块&#xff0c;如下。 二、maven依赖 <dependency><groupId>org.springframework.boot</groupId…