OAuth2.0系列之密码模式实践教程(四)
@
OAuth2.0系列博客:
- OAuth2.0系列之基本概念和运作流程(一)
- OAuth2.0系列之授权码模式实践教程(二)
- OAuth2.0系列之简化模式实践教程(三)
- OAuth2.0系列之密码模式实践教程(四)
- OAuth2.0系列之客户端模式实践教程(五)
- OAuth2.0系列之集成JWT实现单点登录
1、密码模式简介
1.1 前言简介
在上一篇文章中我们学习了OAuth2的一些基本概念,对OAuth2有了基本的认识,接着学习OAuth2.0授权模式中的密码模式
ps:OAuth2.0的授权模式可以分为:
- 授权码模式(authorization code)
- 简化模式(implicit)
- 密码模式(resource owner password credentials)
- 客户端模式(client credentials)
密码模式(resource owner password credentials):密码模式中,用户向客户端提供自己的用户名和密码,这通常用在用户对客户端高度信任的情况
1.2 授权流程图
官网图片:
- (A)用户访问客户端,提供URI连接包含用户名和密码信息给授权服务器
- (B)授权服务器对客户端进行身份验证
- (C)授权通过,返回acceptToken给客户端
从调接口方面,简单来说:
- 第一步:直接传useame,password获取token
- 第二步:拿到acceptToken之后,就可以直接访问资源
http://localhost:8084/api/userinfo?access_token=${accept_token}
2、例子实践
2.1 实验环境准备
- IntelliJ IDEA
- Maven3.+版本
新建SpringBoot Initializer项目,可以命名password
主要是想引入:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency> <!-- Spring Cloud Oauth2--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></dependency><!-- Spring Cloud Security--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-security</artifactId></dependency>
2.2 OAuth2.0角色
前面的学习,我们知道了OAuth2.0主要包括如下角色,下面通过代码例子加深对理论的理解
- 资源所有者(Resource Owner)
- 用户代理(User Agent)
- 客户端(Client)
- 授权服务器(Authorization Server)
- 资源服务器(Resource Server)
生产环境、资源服务器和授权服务器一般是分开的,不过学习的可以放在一起
定义资源服务器,用注解@EnableResourceServer;
定义授权服务器,用注解@EnableAuthorizationServer;
2.3 OAuth2.0配置类
package com.example.oauth2.password.config;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;import org.springframework.security.oauth2.provider.token.TokenStore;import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;/** * <pre> * OAuth2.0配置类 * </pre> * * <pre> * @author mazq * 修改记录 *修改后版本: 修改人: 修改日期: 2020/06/11 11:00 修改内容: * </pre> */@Configuration//开启授权服务@EnableAuthorizationServerpublic class OAuth2Config extends AuthorizationServerConfigurerAdapter {@Autowiredprivate AuthenticationManager authenticationManager;private static final String CLIENT_ID = "cms";private static final String SECRET_CHAR_SEQUENCE = "{noop}secret";private static final String SCOPE_READ = "read";private static final String SCOPE_WRITE = "write";private static final String TRUST = "trust";private static final String USER ="user";private static final String ALL = "all";private static final int ACCESS_TOKEN_VALIDITY_SECONDS = 2*60;private static final int FREFRESH_TOKEN_VALIDITY_SECONDS = 2*60;// 密码模式授权模式private static final String GRANT_TYPE_PASSWORD = "password";//授权码模式private static final String AUTHORIZATION_CODE = "authorization_code";//refresh token模式private static final String REFRESH_TOKEN = "refresh_token";//简化授权模式private static final String IMPLICIT = "implicit";//指定哪些资源是需要授权验证的private static final String RESOURCE_ID = "resource_id";@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients// 使用内存存储.inMemory()//标记客户端id.withClient(CLIENT_ID)//客户端安全码.secret(SECRET_CHAR_SEQUENCE)//为true 直接自动授权成功返回code.autoApprove(true).redirectUris("http://127.0.0.1:8084/cms/login") //重定向uri//允许授权范围.scopes(ALL)//token 时间秒.accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS)//刷新token 时间 秒.refreshTokenValiditySeconds(FREFRESH_TOKEN_VALIDITY_SECONDS)//允许授权类型.authorizedGrantTypes(GRANT_TYPE_PASSWORD );}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {// 使用内存保存生成的tokenendpoints.authenticationManager(authenticationManager).tokenStore(memoryTokenStore());}/** * 认证服务器的安全配置 * * @param security * @throws Exception */@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security//.realm(RESOURCE_ID)// 开启/oauth/token_key验证端口认证权限访问.tokenKeyAccess("isAuthenticated()")// 开启/oauth/check_token验证端口认证权限访问.checkTokenAccess("isAuthenticated()")//允许表单认证.allowFormAuthenticationForClients();}@Beanpublic TokenStore memoryTokenStore() {// 最基本的InMemoryTokenStore生成tokenretu new InMemoryTokenStore();}}
2.4 Security配置类
为了测试,可以进行简单的SpringSecurity
package com.example.oauth2.password.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.annotation.Order;import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.builders.WebSecurity;import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;/** * <pre> * SpringSecurity配置类 * </pre> * * <pre> * @author mazq * 修改记录 *修改后版本: 修改人: 修改日期: 2020/06/11 11:23 修改内容: * </pre> */@Configuration@EnableWebSecurity@Order(1)public class SecurityConfig extends WebSecurityConfigurerAdapter {@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {retu super.authenticationManagerBean();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {//auth.inMemoryAuthentication()auth.inMemoryAuthentication().withUser("nicky").password("{noop}123").roles("admin");}@Overridepublic void configure(WebSecurity web) throws Exception {//解决静态资源被拦截的问题web.ignoring().antMatchers("/asserts/**");web.ignoring().antMatchers("/favicon.ico");}@Overrideprotected void configure(HttpSecurity http) throws Exception {http// 配置登录页并允许访问//.formLogin().permitAll()// 配置Basic登录//.and().httpBasic()// 配置登出页面.logout().logoutUrl("/logout").logoutSuccessUrl("/")// 配置允许访问的链接.and().authorizeRequests().antMatchers("/oauth/**", "/login/**", "/logout/**","/api/**").permitAll()// 其余所有请求全部需要鉴权认证.anyRequest().authenticated()// 关闭跨域保护;.and().csrf().disable();}}
2.5 功能简单测试
接口测试,要用POST方式,在postman测试,response_type参数传password:
http://localhost:8888/oauth/token?password=123&grant_type=password&useame=nicky&scope=all
注意配置一下请求头的授权参数,useame即client_id,password即client_secret
代码方式请求,可以进行如下封装,即进行base64加密
HttpHeaders headers = new HttpHeaders();byte[] key = (clientId+":"+clientSecret).getBytes();String authKey = new String(Base64.encodeBase64(key));LOG.info("Authorization:{}","Basic "+authKey);headers.add("Authorization","Basic "+authKey);
拿到token直接去调业务接口:
http://localhost:8888/api/userinfo?access_token=61b113f3-f1e2-473e-a6d7-a0264bfdfa8d
例子代码下载:code download
作者:smileNicky
来源链接:https://www.cnblogs.com/mzq123/p/13094747.html
版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。
2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。