Sso
即多个站点共用一台认证授权服务器,用户在站点登录后,可以免登录访问其他所有站点
Oauth2 协议 授权第三方进行认证
resource owner:资源所有者,这里可以理解为用户。 security (yyl-123456)
client:客户端,可以理解为一个第三方的应用程序 即微博 CSDN。(oauth admin 123456)
authorization server:(sso)
认证/授权服务器,它认证resource owner的身份,为 resource owner提供授权审批流程,并最终颁发授权令牌(Access Token)。
resource server:资源服务器: 除了认证服务器之外的其他的服务器
微服务项目里面认证服务器只能有一台
资源服务器多台
Oauth2
四个角色:
resource owner:资源所有者,这里可以理解为用户。
client:客户端,可以理解为一个第三方的应用程序 即微博 CSDN。
resource server:资源服务器,它存储用户或其它资源。
authorization server:
认证/授权服务器,它认证resource owner的身份,为 resource owner提供授权审批流程,并最终颁发授权令牌(Access Token)。
认证服务器只有一个 sysauth
资源服务器 订单 商品 支付
四种授权模式
* authorization_code 授权码模式
* password 密码模式
* implicit 简单模式
* client_credentials 客户端模式
目的: 颁发token
获取token 校验token
认证服务器里面的
常用的路径:
/oauth/authoriz | 授权端点 |
/oauth/token | 令牌端点获取token |
/oauth/confirm_access | 用户确认授权提交端点 |
/oauth/error | 授权服务错误信息端点 |
/oauth/check_token | 用于资源服务访问的令牌解析端点 |
/oauth/token_key | 提供公有密匙的端点,如果你使用JWT(RSA)令牌的 |
搭建认证服务器:
Oauth2
Springsecurity-oauth2
1 创建父项目
2 启动nacos
3 创建授权微服务sys-auth
pom文件:
配置参数
- 加jar
<!--oauth2--> <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> <version>2.3.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> |
授权码模式:
- 访问授权站点生成一个授权码
localhost:8081 指的是认证服务器所在的地址
/oauth/authorize 授权站点路径(框架提供)
http://localhost:8081/oauth/authorize?response_type=code&client_id=admin&scop=all
跳转成功
授权码:SsZ9rE
- 授权码生成token
简单模式:
其他地方不变
http://localhost:8081/oauth/authorize?response_type=token&client_id=admin&scope=all
https://www.baidu.com/#access_token=5037f7b1-da2f-4068-a857-5b21fa4a8251&token_type=bearer&expires_in=43199
客户端模式:
只修改模式,访问授权码模式路径即可,简单修改模式参数
密码模式:
security的配置文件中进行的配置
/**
* 配置密码模式的时候需要这个Bean
* @return
* @throws Exception
*/
@Bean
public AuthenticationManager getAuthManger() throws Exception {
return super.authenticationManagerBean();
}
oauth的配置文件中配置:
/**
* 配置凭证的信息
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
不想重复的输入第三方的用户名和密码
放行
/**
* 安全配置
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients()
.checkTokenAccess("permitAll()")//校验token 放行
.tokenKeyAccess("permitAll()");//获取token的值
}
无登陆用户和密码(参数中有)成功放行
校验token
localhost:8081/oauth/check_token?token=d72c34f2-0a97-47c8-893a-1b3d7a5e74c8
使用jwt类型的token
Jwt 类型 三段 头类型 sign的加密方式
载荷部分:username 资源的信息 过期的时间
签名部分(自己来写的)
Token
加jar
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-jwt</artifactId> <version>1.1.0.RELEASE</version> </dependency> |
配置bean
@Bean
public TokenStore getTokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
/**
* 生成token的bean
* 解析token的bean
*/
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
jwtAccessTokenConverter.setSigningKey("xiaowu");
return jwtAccessTokenConverter;
}
使用bean
/**
* 配置凭证的信息
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.tokenStore(getTokenStore())//token存储的地方
.accessTokenConverter(jwtAccessTokenConverter());//生成token的bean 也是 解析token的bean
}
认证之后直接生成token
安全配置文件中配置认证成功之后使用第三方工具hutool 发出post请求 生成token 返回客户端
配置文件代码
http.formLogin().permitAll().loginProcessingUrl("/userlogin")
.successHandler((httpServletRequest, httpServletResponse, authentication) -> {
//httpServletRequest
String username = httpServletRequest.getParameter("username");
String password = httpServletRequest.getParameter("password");
//hutool工具 发出post请求 获取token的值
HttpRequest post = HttpUtil.createPost("http://localhost:8081/oauth/token");//路径
//参数
post.form("grant_type","password");
post.form("client_id","admin");
post.form("client_secret","123456");
post.form("username",username);
post.form("password",password);
//
HttpResponse execute = post.execute();//发送请求
String body = execute.body();
System.out.println(body);
//token的值
//字符串转化为map
JSONObject entries = JSONUtil.parseObj(body);
Object accessToken = entries.get("access_token");
// 返回一个token
printJsonData(httpServletResponse,new Resout<>(200,"成功",accessToken));
//返回一个token
运行成功
资源服务器:
- 加jar
<dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> <version>2.3.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>2.3.5.RELEASE</version> </dependency> |
- 编写配置文件
package com.example.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
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.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(jsr250Enabled = true,prePostEnabled = true,securedEnabled=true)
public class MyResConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
//.access("@RbacConfig.hasPermission(request,authentication)")
.and()
.csrf().disable();
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
jwtAccessTokenConverter.setSigningKey("yyl"); //
return jwtAccessTokenConverter;
}
}
- 写正常的逻辑
- 测试token是否生效
携带token 访问资源服务器
Authorization 放在headers里面的
Token的值 要求必须是bearer 类型的 token前面加上这个类型