sso单点登陆
即多个站点共用一台认证授权服务器,用户在站点登录后,可以免登录访问其他所有站点
Oauth2 协议 授权第三方进行认证
resource owner:资源所有者,这里可以理解为用户。 security (yyl-123456)
client:客户端,可以理解为一个第三方的应用程序 即微博 CSDN。(oauth admin 123456)
authorization server:(sso)
认证/授权服务器,它认证resource owner的身份,为 resource owner提供授权审批流程,并最终颁发授权令牌(Access Token)。
resource server:资源服务器: 除了认证服务器之外的其他的服务器
微服务项目里面 认证服务器只能有一台
资源服务器 多台
Oauth2
* 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、加jar包
<dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> <version>2.5.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
授权码模式
1.访问授权站点 生成一个 授权码
/oauth/authorize 授权站点 路径 (框架提供)
http://localhost:8081/oauth/authorize?response_type=code&client_id=admin&scop=all
2.授权码生成token
localhost:8081/oauth/token?grant_type=authorization_code&code=xn79lm&client_id=admin&redirect_url=http://www.baidu.com&scope=all
简单模式
http://localhost:8081/oauth/authorize?response_type=token&client_id=admin&scop=all
跳转到登陆页面后登陆 成功后在访问这个就会显示token
客户端模式
密码模式
localhost:8081/oauth/token?client_id=admin&scope=all&grant_type=password
更改后访问他会出现以下情况
/** * 配置密码模式的时候需要这个bean * */ @Bean public AuthenticationManager getAuthManger() throws Exception { return super.authenticationManagerBean(); }
/** *配置凭证信息 * */ @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager); }
还需要在路径上面加入它的client_secret 、username 、password等
这样他就可以正常访问
密码模式在路径上用户名和密码都给你了还让我登陆这样不合理我们应该直接放行
安全配置
/** * 安全配置 */ @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security.allowFormAuthenticationForClients() .checkTokenAccess("permitAll()")//校验token 放行 .tokenKeyAccess("permitAll()");//获取token的值 }
配置完成后在访问路径就可以正常访问了
localhost:8081/oauth/token?client_id=admin&grant_type=password&client_secret=123456&username=zzh&password=123456
校验token
访问路径 路径中 /oauth/check_token是用于资源服务访问的令牌解析端点 后跟上token 和值
localhost:8081/oauth/check_token?token=vI9My8L-WB-_r7IrIzHa8doKk3A
JWT类型
三段 头类型 sign的加密方式
载荷部分:username 资源的信息 过期的时间
签名部分 (自己写的)
先加入pom依赖
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-jwt</artifactId> <version>1.1.0.RELEASE</version> </dependency>
在品质凭证信息里面写入存储token的地方也就是.tokenStore(getTokenStore())和生成刷新的bean .accessTokenConverter(jwtAccessTokenConverter())
/** *配置凭证信息 * */ @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager) .tokenStore(getTokenStore())//token存储的地方 .accessTokenConverter(jwtAccessTokenConverter());//生成token的bean 刷新token的bean }@Bean public TokenStore getTokenStore(){ return new JwtTokenStore(jwtAccessTokenConverter()); } /** * * 生成token的bean */ @Bean public JwtAccessTokenConverter jwtAccessTokenConverter(){ JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter(); jwtAccessTokenConverter.setSigningKey("zzh"); return jwtAccessTokenConverter; }
写入完成后重新运行
写入路径生成jwt格式的token
localhost:8081/oauth/token?client_id=admin&grant_type=password&client_secret=123456&username=zzh&password=123456
转换成后登陆后直接返回token的值
http.formLogin() // .loginPage("/login.html") //登录的页面 .loginProcessingUrl("/userlogin") // // .successHandler((request, response, authentication) -> { //request String username = request.getParameter("username"); String password = request.getParameter("password"); //hutool 工具 发出post请求 获取token的值 HttpRequest post = HttpUtil.createPost("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); //字符串转化为map JSONObject entries = JSONUtil.parseObj(body); Object accessToken = entries.get("access_token"); printJsonData(response,new Result(200,"成功",accessToken)); // Result result= Result.success("成功"); // printJsonData(response,result); })//前后端分离的收 认证成功 走的方法
当登陆成功时直接用hutool工具发出post请求根据自己配置的路径和参数发送请求获取token
刚开始获取的是一个字符串这个字符串显然不能直接使用在使用JSONUtil.parseObj();这个方法把字符串转化为map这样登陆成功之后就可以直接获取到JWT格式的token
资源服务器
1.加jar
<dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> <version>2.5.2.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> </dependency>
2.编写配置文件
package com.aaa.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.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 MyresoConfig 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("zzh"); return jwtAccessTokenConverter; } }
3.写正常的逻辑
4.测试token能否生效
携带token访问资源服务器
必须写到头里面Headers
key 必须是Authorization 不能写错
值必须是 bearer 类型的 所以token前面加上bearer可以不加空格