业界提供了OAUTH的多种实现如PHP、JavaScript,Java,Ruby等各种语言开发包,Oauth协议目前发展到2.0版本,1.0版本过于复杂,2.0版本已得到广泛应用。
参考:https://baike.baidu.com/item/oAuth/7153134?fr=aladdin
Oauth协议:https://tools.ietf.org/html/rfc6749
下面是基于OAuth2协议授权码模式实现,微信扫码认证的流程:

具体流程如下:
1、用户点击微信扫码
用户进入登录页面,点击微信的图标开打微信扫码界面。
现在搞清楚几个概念:
资源:用户信息,在微信中存储。
资源拥有者:用户是用户信息资源的拥有者。
认证服务:微信负责认证当前用户的身份,负责为客户端颁发令牌。
客户端:客户端会携带令牌请求微信获取用户信息,黑马程序员网站即客户端,黑马网站需要在浏览器打开。
2、用户授权网站访问用户信息
询问用户是否授权网站访问自己在微信的用户信息,用户点击“确认登录”表示同意授权,微信认证服务器会颁发一个授权码给网站。
只有资源拥有者同意微信才允许网站访问资源。
3、网站获取到授权码
4、携带授权码请求微信认证服务器申请令牌
此交互过程用户看不到。
5、微信认证服务器向网站响应令牌
此交互过程用户看不到。
6、网站请求微信资源服务器获取资源即用户信息。
网站携带令牌请求访问微信服务器获取用户的基本信息。
7、资源服务器返回受保护资源即用户信息
8、网站接收到用户信息,此时用户在网站登录成功。
OAuth2在项目的应用
本项目是前后端分离架构,前端访问微服务资源也可以基于OAuth2协议进行认证。
要接入微信扫码登录所以本项目要使用OAuth2协议访问微信中的用户信息。
OAuth2的授权模式
OAuth2提供授权码模式、密码模式、简化模式、客户端模式等四种授权模式,前边举的微信扫码登录的例子就是基于授权码模式,这四种模式中授权码模式和密码模式应用较多
OAuth2授权码模式测试
要想测试授权模式首先要配置授权服务器即上图中的认证服务器,需要配置授权服务及令牌策略
说明“:AuthorizationServer用 @EnableAuthorizationServer 注解标识并继承AuthorizationServerConfigurerAdapter来配置OAuth2.0 授权服务器。
@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
@Resource(name="authorizationServerTokenServicesCustom")
private AuthorizationServerTokenServices authorizationServerTokenServices;
@Autowired
private AuthenticationManager authenticationManager;
//客户端详情服务
@Override
public void configure(ClientDetailsServiceConfigurer clients)
throws Exception {
clients.inMemory()// 使用in-memory存储
.withClient("XcWebApp")// client_id
.secret("XcWebApp")//客户端密钥
// .secret(new BCryptPasswordEncoder().encode("XcWebApp"))//客户端密钥
.resourceIds("xuecheng-plus")//资源列表
.authorizedGrantTypes("authorization_code", "password","client_credentials","implicit","refresh_token")// 该client允许的授权类型authorization_code,password,refresh_token,implicit,client_credentials
.scopes("all")// 允许的授权范围
.autoApprove(false)//false跳转到授权页面
//客户端接收授权码的重定向地址
.redirectUris("http://www.51xuecheng.cn")
;
}
//令牌端点的访问配置
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.authenticationManager(authenticationManager)//认证管理器
.tokenServices(authorizationServerTokenServices)//令牌管理服务
.allowedTokenEndpointRequestMethods(HttpMethod.POST);
}
//令牌端点的安全配置
@Override
public void configure(AuthorizationServerSecurityConfigurer security){
security
.tokenKeyAccess("permitAll()") //oauth/token_key是公开
.checkTokenAccess("permitAll()") //oauth/check_token公开
.allowFormAuthenticationForClients() //表单认证(申请令牌)
;
}
}
@Configuration
public class TokenConfig {
@Autowired
TokenStore tokenStore;
@Bean
public TokenStore tokenStore() {
//使用内存存储令牌(普通令牌)
return new InMemoryTokenStore();
}
//令牌管理服务
@Bean(name="authorizationServerTokenServicesCustom")
public AuthorizationServerTokenServices tokenService() {
DefaultTokenServices service=new DefaultTokenServices();
service.setSupportRefreshToken(true);//支持刷新令牌
service.setTokenStore(tokenStore);//令牌存储策略
service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时
service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天
return service;
}
}
配置认证管理bean
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
测试。

进入授权页面便可访问资源