http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

1、什么是OAuth
OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛应用。目前的版本是2.0版。
OAuth的作用就是让"客户端"安全可控地获取"用户"的授权,与"服务商提供商"进行互动

OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorization layer)。“客户端"不能直接登录"服务提供商”,只能登录授权层,以此将用户与客户端区分开来。"客户端"登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。
"客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。
2、OAuth2的四种模式:
a、授权码模式(别人来调用我们的服务)
b、简化模式(pc模式,跳过了"授权码"这个步骤)
c、密码模式(自己的服务)
d、客户端模式(服务与服务之间的调用)

一、springcloud + OAuth2
1方案:

添加pom依赖:

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>

认证服务配置:

import com.gao.handler.MyAuthorationFaileHandler;
import com.gao.handler.MyAuthorationSeccuserHandler;
import com.gao.handler.MyAuthorictionDeniedHandler;
import com.gao.service.MyUserDetailService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;@Configuration
@EnableWebSecurity
@EnableGlobalAuthentication //开启全局的注解授权(使用注解授权)
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {/***  配置认证管理器,授权模式为“poassword”时会用到*/@Override@Bean protected AuthenticationManager authenticationManager() throws Exception {return super.authenticationManager();}@Beanpublic PersistentTokenRepository getTokenRepository(){JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();//第一次启动的时候创建表//jdbcTokenRepository.setCreateTableOnStartup(true);return jdbcTokenRepository;}//加密配置@Beanpublic PasswordEncoder getPwdEncoder(){return new BCryptPasswordEncoder();} @Overrideprotected void configure(HttpSecurity http) throws Exception {//查询所有的权限http.exceptionHandling().accessDeniedHandler((new MyAuthorictionDeniedHandler()))//没有权限时返回的信息           .and().authorizeRequests().antMatchers("/login").permitAll()//匹配所有,对登录请求全部放行
//                .antMatchers("/login.html").permitAll()//自定义登录页面放行.anyRequest().authenticated()//比对请求,进行权限验证.and().formLogin()//允许表单登录
//                .successForwardUrl("/succeed")//登录成功后的跳转请路径.successHandler(new MyAuthorationSeccuserHandler()).failureHandler(new MyAuthorationFaileHandler())
//                .loginPage("/login.html")//登录页面
//                .loginProcessingUrl("/login").and().logout().permitAll()//允许所有的退出操作.and().csrf().disable();  //关闭跨站请求//记住我设置http.rememberMe().tokenRepository(getTokenRepository()).userDetailsService(new MyUserDetailService()).tokenValiditySeconds(3600);}
}
import org.springframework.context.annotation.Bean;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.List;@Service
public class MyUserDetailService implements UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {//根据传入的用户名去数据库查询用户//判断是否为空,//空,抛出异常//非空,返回用户List<GrantedAuthority> authorities = new ArrayList<>();//查询权限List<Object> userPremis = new ArrayList<>();userPremis.forEach(t->{SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("权限值");authorities.add(simpleGrantedAuthority);});
//        public User(String username, String password, Collection<? extends GrantedAuthority > authorities) {//            this(username, password, true, true, true, true, authorities);
//        }return new User("username","password",authorities);}
}

授权服务配置:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
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.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.JdbcAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;import javax.annotation.Resource;
import javax.sql.DataSource;@Configuration@EnableAuthorizationServer //开启授权服务配置,声明该服务作为授权服务方
public class MyAuthSecurityConfig extends AuthorizationServerConfigurerAdapter {//授权服务安全配置:配置哪些路径放行(检查token的路径要放行)@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.checkTokenAccess("permitAll()")   //对应/oauth/check_token ,路径公开.allowFormAuthenticationForClients(); //允许客户端进行表单身份验证,使用表单认证申请令牌}@Resourceprivate DataSource dataSource;@Resourceprivate BCryptPasswordEncoder bCryptPasswordEncoder;/*客户端详情:配置客户端请求的参数ClientDetailsServiceConfigurer 是这对于客户端详情的配置,我们通过withClientDetails关联一个JdbcClientDetailsService,默认会去找数据库中的名字为 oauth_client_details 表中的数据作为客户端详情的配置*/@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.withClientDetails(getDetailsService());} public ClientDetailsService getDetailsService(){JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource); jdbcClientDetailsService.setPasswordEncoder(bCryptPasswordEncoder);return jdbcClientDetailsService;}@Resourceprivate AuthenticationManager authenticationManager;//授权服务端点:配置授权码和令牌的管理/存储方式@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.authenticationManager(authenticationManager);endpoints.authorizationCodeServices(getCodeServices()); //授权码的管理服务 ,默认读取 oauth_code表endpoints.tokenServices(getTokenServices()); //令牌的管理服务endpoints.allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST);}@Beanpublic AuthorizationServerTokenServices getTokenServices() {DefaultTokenServices services = new DefaultTokenServices();services.setClientDetailsService(getDetailsService()); //指定客户端详情配置services.setSupportRefreshToken(true);  //支持产生刷新tokenservices.setTokenStore(declareTokenStore()); //token存储方式return services;}//基于内存的Token存储public TokenStore declareTokenStore() {return new InMemoryTokenStore();}@Beanpublic AuthorizationCodeServices getCodeServices() {return new JdbcAuthorizationCodeServices(dataSource);}
}

1、ClientDetailsServiceConfigurer :用来配置客户端详情服务:如配置客户端id(client_id)资源id、客户端密钥(secrect)、授权方式、scope等,可以基于内存或jdbc。(可以理解为是对浏览器向授权服务器获取授权码或令牌时需要提交的参数配置)
2、AuthorizationServerEndpointsConfigurer:配置令牌的访问端点url和令牌服务,如配置如何管理授权码(内存或jdbc),如何管理令牌(存储方式,有效时间等等)
3、AuthorizationServerSecurityConfigurer: 用来配置令牌端点的安全约束,如配置对获取授权码,检查token等某些路径进行放行

创建客户端详情配置表SQL

DROP TABLE IF EXISTS `oauth_client_details`;
CREATE TABLE `oauth_client_details` (`client_id` varchar(48) NOT NULL,`resource_ids` varchar(256) DEFAULT NULL,`client_secret` varchar(256) DEFAULT NULL,`scope` varchar(256) DEFAULT NULL,`authorized_grant_types` varchar(256) DEFAULT NULL,`web_server_redirect_uri` varchar(256) DEFAULT NULL,`authorities` varchar(256) DEFAULT NULL,`access_token_validity` int(11) DEFAULT NULL,`refresh_token_validity` int(11) DEFAULT NULL,`additional_information` varchar(4096) DEFAULT NULL,`autoapprove` varchar(256) DEFAULT NULL,PRIMARY KEY (`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;`

创建授权码SQL

DROP TABLE IF EXISTS `oauth_code`;
CREATE TABLE `oauth_code` (
`code` varchar(255) DEFAULT NULL COMMENT '授权码(未加密)',
`authentication` varbinary(5000) DEFAULT NULL COMMENT 'AuthorizationRequestHolder.java对象序列化后的二进制数据'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

授权测试:
第一步,通过浏览器获取授权码,GET访问:

http://localhost:8100/oauth/authorize?client_id=webapp2&response_type=code&redirect_uri=http://www.baidu.com

第二步,使用Postmain获取令牌,Post访问

http://localhost:8100/oauth/token?client_id=webapp2&client_secret=123&grant_type=authorization_code&code=gD8ZbB&redirect_uri=http://www.baidu.com

刷新token:

http://localhost:8100/oauth/token?grant_type=refresh_token&refresh_token=刷新Token值&client_id=webapp&client_secret=secret

资源方配置

在资源服务中我们需要解决的问题是,当请求进来,请求是需要携带token,我们需要配置资源服务如何对token进行校验和授权

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;@Configuration
@EnableResourceServer //作为资源服务方
public class MyRresourceServerConfig extends ResourceServerConfigurerAdapter {@Overridepublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {resources.resourceId("courseId");resources.tokenServices(getResourceTokenServices());}@Beanpublic ResourceServerTokenServices getResourceTokenServices() {//使用远程服务请求授权服务器校验token , 即:资源服务和授权服务器不在一个主机RemoteTokenServices services = new RemoteTokenServices();//授权服务地址 , 当浏览器访问某个资源时就会调用该远程授权服务地址去校验token//要求请求中必须携带tokenservices.setCheckTokenEndpointUrl("http://localhost:8100/oauth/check_token");//客户端id,对应认证服务的客户端详情配置的clientIdservices.setClientId("webapp");//密钥,对应认证服务的客户端详情配置的clientIdservices.setClientSecret("123");return services;}/*** http安全配置* @param http* @throws Exception*/@Overridepublic void configure(HttpSecurity http) throws Exception {http.authorizeRequests()//校验scope必须为all , 对应认证服务的客户端详情配置的clientId.antMatchers("/**").access("#oauth2.hasScope('all')")//关闭跨域伪造检查.and().csrf().disable()//把session设置为无状态,意思是使用了token,那么session不再做数据的记录.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);}
}

单点登录:
sso single sign on
在一个站点登录,其他站点在一定时间内都不用重现登录

共享token
Cookie:
cookie可以跨站。cookie不可跨域调用。每次请求一个新的页面的时候cookie都会被发送过去
sessionstorage
sessionStorage是在同源的窗口中,始终存在数据。也就是说,这个浏览器没有关闭,即使刷新页面或进入到同源另一个页面,数据仍然存在,关闭后,sessionstorage就会被销毁。
localstorage

无感刷新:
如果用户还在操作,此时token过期了,应该系统自动获取新token
1、如果token过期了,访问后台报错,报错了如果是过期的异常,全局异常中捕获该异常,捕获以后重新获取新的token 返回给前端。
2、在过期时间还有5分钟的时候,前端主动发送一个请求
3.1、在离过期时间还有5分钟之内自动刷新token
3.2、最后一次操作在过期时间之后,但是离上一次操作的时间差值在30分钟之内

outTime :过期时间
curTime :当前时间
lastTime : 最后一次操作时间
过期前5分钟内自动刷新
if(outTime - curTime < 5 && outTime - curTime > 0){
//刷新token
}$.cookie("lastTime",lastTime)if(lastTime > outTime  && cutTime > expTime  && curTime - lastTime <=30){
//刷新token
}
$.token('lastTime',curTime)

【注意】当配置域名之后,在访问页面的时候使用域名进行访问。避免无法使用cookie

springcloud + oauth2相关推荐

  1. Java开源项目:saas小程序商城(SpringCloud + Oauth2.0 + ShiroRedis + JWT + Gateway + Nacos + Nginx+Vue+Mysql)

    项目采用**SpringCloud **主流开源框架,,设计轻巧,使用简单,开发人员接手与二次开发简单易懂: 项目完成了对阿里云.腾讯云.微信生态的快速接入与代码示例,并成功运用到了商业中,方便大家学 ...

  2. SpringCloud Oauth2认证 基础版本

    理解什么是OAUTH2 OAuth2是什么 OAuth 就是一种授权机制,数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据.系统从而产生一个短期的进入令牌(token),用来代替密码,供 ...

  3. SpringCloud+OAuth2+Redis实现的微服务统一认证授权

    作者:myCat blog.csdn.net/WYA1993/article/details/85050120 开发环境: Windows10 Intellij Idea2018.2 jdk1.8 r ...

  4. springboot springcloud oauth2 jwt redis 框架脚手架

    转载请表明出处 https://blog.csdn.net/Amor_Leo/article/details/103662117 谢谢 源码 我的GitHub 详情 v1 v1是oauth2 的cli ...

  5. SpringCloud - Oauth2增加短信验证码验证登录

    文章目录 前言 Oauth2认证过程 1.在进行认证时,会先根据认证类型即前端传入的grant_type,从所有的TokenGranter中找到具体匹配的TokenGranter 2.在找到对应的To ...

  6. 基于SpringCloud + Oauth2.0 + ShiroRedis + JWT + Gateway + Nacos + Nginx + Vue实现的SaaS数字商城系统

    文章目录 一.什么是SaaS? 二.数字商城系统介绍 三.技术栈以及项目特点 四.系统设计 五.系统部分功能演示

  7. SpringCloud学习总结

    SpringCloud 一,微服务架构 1 架构演变 单体架构 =>垂直应用架构 =>SOA架构 => 微服务架构 2 微服务架构: 微服务架构和SOA架构很明显的一个区别就是服务拆 ...

  8. Gson解析空字符串异常的处理

    更多前沿课程:元宇宙:人类社会数字化转型(开学第一课)--机器学习视频教程-人工智能-CSDN程序员研修院 https://edu.csdn.net/course/detail/30449 Sprin ...

  9. 微服务开放平台接口设计

    什么是开放平台接口 在一些大型互联网公司,随着公司的业务发展逐渐庞大,需要和外部合伙伙伴进行合作,需要将公司的接口开放给外部其他合伙伙伴进行调用. 比如腾讯的 QQ互联网.微信开放平台.蚂蚁金服开放平 ...

最新文章

  1. 【译】使用Kotlin和RxJava测试MVP架构的完整示例 - 第1部分
  2. ifstream java_C ifstream将读取一些值然后停止
  3. 图像的稀疏表示——ScSPM和LLC的总结
  4. 记录java应用部署到k8s中
  5. 【Git】解决remote: ******: Incorrect username or password (access token)方法
  6. JDBC查询Oracle全部表名称,如何使用JDBC API从Oracle数据库中的现有表中检索记录?...
  7. python标准库os中的方法_python中OS常用方法
  8. linux ntp时间立即同步命令_记一次生产环境部署NTP服务及配置时间同步
  9. WebServices中的SOAP究竟是什么东西?与http,xml,webservices的本质关系是什么?
  10. Android 进程间通信——AIDL
  11. C#鼠标点击器-没有测试-转自http://hi.baidu.com/syq_ghost/item/2cc253eb538b72e7fb42ba44
  12. 进击的UI------------UIToolBar(bottom导航条)
  13. 应用安全 - Web安全 - 逻辑漏洞整理
  14. 超详细JDK下载与安装步骤
  15. 大姨吗的戏 投资人的伤
  16. 直流无刷电机无感检测电路原理
  17. codevs 5960 信使
  18. 定制ERP和通用ERP如何选择?
  19. CSS学习笔记7PS切图与仿学成在线例子
  20. 人生无意义,才更值得过,推石上山的搏斗本身,足以充实一颗人心,认清生活的荒诞,对它报之以微笑,就是对抗荒诞的最好方式

热门文章

  1. sdut-循环-7-统计正数和负数的个数(II)python
  2. 比你拼命的人多的是,最可怕的是比你牛的人比你还拼命(每天看一段一个月刚刚好)
  3. 北大青鸟天府校区IT学习大揭秘
  4. 物理机服务器重装nvidia显卡驱动
  5. 解决Mac绿联 拓展坞 网线接口无法使用问题
  6. 更靠近明媚阳光的日子里
  7. R语言ggplot2可视化:patchwork包(直接使用加号+)将一个ggplot2可视化结果和一段文本内容横向组合起来形成最终结果图、使用wrap_elements函数将文本内容放置在组合组左边
  8. C# winform程序调用Console控制台办法
  9. DFT的一些基本性质
  10. Python爬虫:短视频平台无水印下载(上)