1.四种授权方式(简化模式省略)
授权码模式(authorization code)
-
资源拥有者访问客户端,客户端要求资源拥有者授权(浏览器重定向到授权服务器,并携带着客户端本身的信息,这里要求客户端本身要在授权服务器中有记录)。
-
浏览器出现授权服务器授权页面,用户授权。
/uaa/oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http://www.baidu.com -
授权服务器在经过用户同意授权之后,将授权码转经浏览器(就是在客户端配置的返回的重定向url地址,redirect_uri)返回给客户端。
-
客户端拿着授权码 再次向授权服务器索要access_token。
/uaa/oauth/token?client_id=c1&client_secret=secret&grant_type=authorization_code&code=5PgfcD &redirect_uri=http://www.baidu.com
虽然过程是四种中最复杂的,但也是最安全的,为了安全不在乎这些性能损耗和逻辑。其实逻辑也还好。
密码模式
资源拥有者将用户名和密码 发送给客户端,客户端拿着用户名和密码向资源服务器请求令牌(access_token)。
适用范围:既然将用户名和密码 交给了客户端,那么就意味着风险。所以该方法适用于我们自己开发的客户端。
客户端模式
拿着客户端id+访问类型,就可以直接获取访问令牌。
前提是:非常信任这个客户端
授权码模式配置
授权码用的最多,这边详细说一下授权码的配置。
授权服务器 继承AuthorizationServerConfigurerAdapter
@Configuration
@EnableAuthorizationServer //声明是资源授权服务器
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
//这边三个配置 配置具体内容 查看父类
public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer {
//配置客户端信息
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
}
//配置授权服务器 令牌访问端点和令牌服务
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
}
//配置令牌端点约束,哪些可以通过,哪些要拦截
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
}
}
捞一下别人的写好的代码。
@Configuration
@EnableAuthorizationServer
public class OauthServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private DataSource dataSource; //注入application.yml中配置的数据源
@Autowired
private AuthenticationManager authenticationManager; //认证管理器
@Autowired
private UserDetailsService userDetailsService; //查询数据库
//从数据库中查询出客户端信息
@Bean
public JdbcClientDetailsService clientDetailsService() {
return new JdbcClientDetailsService(dataSource);
}
//token保存策略 (有基于内存的(InMemoryTokenStore),有基于数据库的(JdbcTokenStore),还有个最牛逼的jwt(JwtTokenStore)
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
//授权信息保存策略
@Bean
public ApprovalStore approvalStore() {
return new JdbcApprovalStore(dataSource);
}
//授权码模式专用对象
@Bean
public AuthorizationCodeServices authorizationCodeServices() {
return new JdbcAuthorizationCodeServices(dataSource);
}
//指定客户端登录信息来源
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService());
}
//配置 令牌端点约束
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.allowFormAuthenticationForClients();
oauthServer.checkTokenAccess("isAuthenticated()"); // /oauth/check_token安全配置地址 将checkTokenAccess完全放开,所有人都可以访问。
}
//配置 令牌端点和令牌服务
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.approvalStore(approvalStore())
.authenticationManager(authenticationManager) //匹配 密码服务的
.authorizationCodeServices(authorizationCodeServices()) //匹配 授权码服务的
.tokenStore(tokenStore());
}
资源服务器配置
和上面的一样。开启资源服务注解@EnableResourceServer,和继承资源服务器配置适配器ResourceServerConfigurerAdapter,并实现其中的两个方法。
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResouceServerConfig extends ResourceServerConfigurerAdapter {
public static final String RESOURCE_ID = "res1";
//资源服务令牌解析服务,远程调用授权服务中接口去 验证token。 加了这个才是完整的授权服务!!
@Bean
public ResourceServerTokenServices tokenService() {
//使用远程服务请求授权服务器校验token,必须指定校验token 的url、client_id,client_secret
RemoteTokenServices service=new RemoteTokenServices();
service.setCheckTokenEndpointUrl("http://localhost:53020/uaa/oauth/check_token");
service.setClientId("c1");
service.setClientSecret("secret");
return service;
}
/**
* tokenServices: ResourceServerTokenServices 类的实例,用来实现令牌服务
* resourceId: 资源服务的id
* tokenStore: token存储策略,指定令牌从哪获取,是jwt呢,还是数据库,还是内存。
*/
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID)
.tokenServices(tokenService())
.stateless(true);
}
/**
* HttpSecurity配置这个与Spring Security类似:
* 请求匹配器,用来设置需要进行保护的资源路径,默认的情况下是保护资源服务的全部路径。
* 通过http.authorizeRequests()来设置受保护资源的访问规则
* 其他的自定义权限保护规则通过 HttpSecurity 来进行配置。
*/
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**").access("#oauth2.hasScope('all')")
.and().csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
另外springsecurity中的WebSecurityConfigurerAdapter这个中
protected void configure(HttpSecurity http) throws Exception {}配置安全拦截机制也是非常重要的。