爬了两天的坑终于上来了,看别人写的很简单,本身写的时候就各类问题,网上SSO文章不少,写的时候就各类问题(本身太菜了)。记录一下,之后方便查看。html
关于OAuth2认证和受权服务器见上一篇java
zheyday.github.io/2019/10/07/…git
项目地址:github
sso分支spring
参考资料:浏览器
www.cnblogs.com/cjsblog/p/1…服务器
阮一峰OAuth2讲解 blog.csdn.net/WSM960921/a…cookie
英文全称single Sign On,中文名单点登陆。就是在多应用系统中,用户只须要登陆一次就能够访问全部信任服务。SSO经过将用户登录信息映射到浏览器cookie中,解决其余服务免登录获取用户session的问题。session
项目中一个有5个模块:
oauth-server是认证和受权服务,负责令牌的发放
zuul是网关服务,实现统一受权
eureka-client和eureka-client1是两个应用服务
eureka-server-single是eureka注册中心
要实现的功能就是经过zuul端口访问eureka-client,首次须要登陆,而后内部跳转到oauth-server中进行认证和受权,成功以后也能够不用登陆访问eureka-client1。
详见
zheyday.github.io/2019/10/07/…
更改了几个地方
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("zuul")
.secret(new BCryptPasswordEncoder().encode("secret"))
.scopes("app")
.authorizedGrantTypes("authorization_code", "password")
.redirectUris("http://localhost:9110/login")
;
// clients.withClientDetails(new JdbcClientDetailsService(dataSource));
}
复制代码
这个函数能够为其余模块资源服务器提供校验
@RestController
@RequestMapping("/oauth2_token")
public class UserController {
@GetMapping("/current")
public Principal user(Principal principal) {
return principal;
}
}
复制代码
@Override
public void configure(HttpSecurity http) throws Exception {
http
// antMatcher表示只能处理/oauth2_token的请求
.antMatcher("/oauth2_token/**")
.authorizeRequests()
.anyRequest().authenticated()
;
}
复制代码
添加了根地址,也就是每次访问这个服务都要加上 /oauth-server
server:
port: 9120
# url根地址 不配置的话会报invalid_token错误
# 或者在zuul中配置也能够
servlet:
context-path: /oauth-server
复制代码
zuul做为系统的入口,提供路由、统一受权等功能。
依赖见项目中
注意:全部模块都引入了spring-cloud-starter-oauth2依赖,因此放入了项目的公共pom.xml中,实现oauth2只须要引用这一个就能够
贴出主要配置,详细见项目中
sensitiveHeaders:
这个必需要。zuul在转发路由时,会改写request中的头部信息,设置成空就是不过滤
security.oauth2.resource:这个是和解析令牌相关的配置
资源服务器须要解析令牌验证正确性,方式有三种:
zuul:
routes:
eureka-client:
path: /eureka-client/**
sensitiveHeaders:
serviceId: eureka-client
eureka-client1:
path: /eureka-client1/**
sensitiveHeaders:
serviceId: eureka-client1
oauth-server:
path: /oauth-server/**
sensitiveHeaders:
serviceId: eureka-client
#认证服务器地址
oauth-server: http://localhost:9120/oauth-server
security:
oauth2:
# 和认证服务器中的client设置对应
client:
client-id: zuul
client-secret: secret
# 获取令牌地址
access-token-uri: ${oauth-server}/oauth/token
# 认证地址
user-authorization-uri: ${oauth-server}/oauth/authorize
resource:
# 进行令牌校验
# 1、访问controller获取Principal
# user-info-uri: ${oauth-server}/oauth2_token/current
# prefer-token-info: false
# 2、访问受权服务器获取公钥 解析令牌
jwt:
key-uri: ${oauth-server}/oauth/token_key
复制代码
整个zuul模块只要添加这一个配置就能够
@EnableOAuth2Sso
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
//须要受权的url
.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and().csrf().disable()
;
}
}
复制代码
新添以下,用于验证请求的令牌是否正确
security:
oauth2:
resource:
id: eureka-client
# 资源服务器三种验证令牌方法
# 1、在ResourceServerConfig中本地配置
# 2、从认证服务器获取用户信息 解析出token
# user-info-uri: ${oauth-server}/oauth2_token/current
# prefer-token-info: false
# 3、远程获取公钥 解析token
jwt:
key-uri: ${oauth-server}/oauth/token_key
复制代码
资源服务器只须要添加这一个配置便可
@Configuration
@EnableResourceServer
//Spring Security默认禁用注解 这里开启注解
// 结合@PreAuthorize("hasRole('admin')")用来判断用户对某个控制层的方法是否有访问权限
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
// 配置须要权限的url
.authorizeRequests()
.anyRequest().authenticated()
.and().csrf().disable();
;
}
//如下就是验证令牌的本地方法 若是使用这种,将上述application.yml的配置注释掉,同时将oauth2.jks放入resources文件夹
// @Override
// public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
// resources.resourceId("app").tokenStore(tokenStore());
// }
//
// @Bean
// public TokenStore tokenStore() {
// return new JwtTokenStore(jwtAccessTokenConverter());
// }
//
// /**
// * 非对称加密算法对token进行签名
// *
// * @return
// */
// @Bean
// public JwtAccessTokenConverter jwtAccessTokenConverter() {
// final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
// // 导入证书
// KeyStoreKeyFactory keyStoreKeyFactory =
// new KeyStoreKeyFactory(new ClassPathResource("oauth2.jks"), "mypass".toCharArray());
// converter.setKeyPair(keyStoreKeyFactory.getKeyPair("oauth2"));
// return converter;
// }
}
复制代码
注意:
若是使用本地验证方法,可能会报读取不到oauth2.jks的错误,由于默认不引用resources目录下的文件,须要在pom.xml中<build>下添加配置
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.*</include>
</includes>
</resource>
</resources>
复制代码
启动顺序:
经过zuul端口访问eureka-client下的方法 http://localhost:9110/eureka-client/hi
会自动跳到oauth-server的登录页面,输入用户名和密码登录
看url,跳转到了oauth/authorize,这是受权接口,而且后面携带了一些zuul配置的信息
成功
访问eureka-client1不须要登录
写的比较简洁,可是作出来真的花费了两天的时间精力(仍是太菜了)
没有什么文采,原理性的东西也写不出来,只能记录一下实践,你们共同交流
更多文章见我的博客 zheyday.github.io/