认证服务器,资源服务器
oauth2.0–基础–03–简单搭建认证服务器,资源服务器
代码文章
https://gitee.com/DanShenGuiZu/learnDemo/tree/master/auth2.0--learn/simple-auth2.0/oauth_parent
- 1
1、整体代码
- 框架:spring sercurity+oauth2.0
1.1、代码结构
- oauth_parent:父工程
- oauth-authorizationServer:认证服务器
- oauth-ResourceServer:资源服务器
2、oauth_parent:父工程代码
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>oauth-learn</groupId><artifactId>oauth-parent</artifactId><version>1.0-SNAPSHOT</version><packaging>pom</packaging>
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.3.RELEASE</version>
</parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version>
</properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Greenwich.RELEASE</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency><dependency><groupId>javax.interceptor</groupId><artifactId>javax.interceptor-api</artifactId><version>1.2</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.0</version></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-jwt</artifactId><version>1.0.10.RELEASE</version></dependency><dependency><groupId>org.springframework.security.oauth.boot</groupId><artifactId>spring-security-oauth2-autoconfigure</artifactId><version>2.1.3.RELEASE</version></dependency></dependencies>
</dependencyManagement><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin><plugin><artifactId>maven-resources-plugin</artifactId><configuration><encoding>utf-8</encoding><useDefaultDelimiters>true</useDefaultDelimiters></configuration></plugin></plugins>
</build>
</project>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
3、认证服务器代码:oauth-authorizationServer
3.1、代码
UserAuthorizeBean
package com.feizhou.oauth.bean;
import lombok.Data;
/**
- 描述该类- JPA
- @author zhoufei
- @class: UserBean
- @date 2020/10/27 16:09
- @Verson 1.0 -2020/10/27 16:09
- @see
*/
@Data
public class UserAuthorizeBean {
private Long id;
private Long userId;
private String authorizeCode;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
UserBean
package com.feizhou.oauth.bean;
import lombok.Data;
/**
- 描述该类- JPA
- @author zhoufei
- @class: UserBean
- @date 2020/10/27 16:09
- @Verson 1.0 -2020/10/27 16:09
- @see
*/
@Data
public class UserBean {
private Long id;
private String userName;
private String password;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
AuthorizationServer
package com.feizhou.oauth.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
/**
- 描述该类- JPA
- @author zhoufei
- @class: AuthorizationServer
- @date 2020/10/28 21:26
- @Verson 1.0 -2020/10/28 21:26
- @see
*/
@Configuration
@EnableAuthorizationServer // 配置授权服务。
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
// 用来配置客户端详情服务
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {// 这里是第三方合作用户的客户id,秘钥的配置// 使用in-memory存储clients.inMemory()// client_id,用户账号.withClient("c1")// 客户端密钥.secret(new BCryptPasswordEncoder().encode("secret"))// 资源列表,资源标识.resourceIds("res1")// 授权类型(4种).authorizedGrantTypes("authorization_code", "password", "client_credentials", "implicit","refresh_token")// 客戶端允许的授权范围.scopes("all")// false跳转到授权页面,让用户点击授权,如果是true,相当于自动点击授权,就不跳转授权页面.autoApprove(false)//// 加上验证回调地址,返回授权码信息.redirectUris("http://www.baidu.com");// 如果有多个用户,配置多个客户详情// .and().withClient()}@Autowired
// 令牌存储策略
private TokenStore tokenStore;
@Autowired
// 客户端详情服务,也就是configure(ClientDetailsServiceConfigurer clients)方法
private ClientDetailsService clientDetailsService;// 令牌管理服务
@Bean
public AuthorizationServerTokenServices tokenService() {DefaultTokenServices service = new DefaultTokenServices();service.setClientDetailsService(clientDetailsService);service.setSupportRefreshToken(true);// 支持刷新service.setTokenStore(tokenStore);// 令牌存储service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天return service;
}@Autowired
// 授权码服务
private AuthorizationCodeServices authorizationCodeServices;
@Autowired
// 认证管理
private AuthenticationManager authenticationManager;
@Autowired
// 令牌管理服务
private AuthorizationServerTokenServices authorizationServerTokenServices;@Override
// 用来配置令牌(token)的访问端点
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {endpoints// 密码模式需要.authenticationManager(authenticationManager)// 授权码模式需要.authorizationCodeServices(authorizationCodeServices)// 令牌管理服务.tokenServices(authorizationServerTokenServices).allowedTokenEndpointRequestMethods(HttpMethod.POST);// 允许post提交
}@Bean
// 授权码服务器
public AuthorizationCodeServices authorizationCodeServices() {// 授权码模式的授权码采用内存方式存储return new InMemoryAuthorizationCodeServices();
}@Override
// 用来配置令牌端点的安全约束,拦截规则
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security// 提供公有密匙的端点,如果你使用JWT令牌的话, 允许.tokenKeyAccess("permitAll()")// oauth/check_token:用于资源服务访问的令牌解析端点,允许.checkTokenAccess("permitAll()")// 表单认证,申请令牌.allowFormAuthenticationForClients();
}@Bean
// 令牌存储策略
public TokenStore tokenStore() {// 内存存储,普通令牌return new InMemoryTokenStore();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
WebSecurityConfig
package com.feizhou.oauth.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
@author Administrator
@version 1.0
**/
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {// 认证管理器
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}// 密码编码器
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}// 安全拦截机制
@Override
protected void configure(HttpSecurity http) throws Exception {
http.
csrf().disable().authorizeRequests().antMatchers("/admin/p1").hasAnyAuthority("p1").antMatchers("/user/p2").hasAnyAuthority("p2").antMatchers("/login*").permitAll().anyRequest().authenticated().and().formLogin();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
UserDao
package com.feizhou.oauth.dao;
import java.util.ArrayList;
import java.util.List;
import com.feizhou.oauth.bean.UserAuthorizeBean;
import com.feizhou.oauth.bean.UserBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
/**
- 描述该类- JPA
- @author zhoufei
- @class: UserBean
- @date 2020/10/27 16:09
- @Verson 1.0 -2020/10/27 16:09
- @see
*/
@Repository
public class UserDao {
@Autowired
JdbcTemplate jdbcTemplate;
// 根据账号查询用户信息
public UserBean getUserByUsername(String username) {String sql = "select * from user where user_name = ?";// 连接数据库查询用户List<UserBean> list = jdbcTemplate.query(sql, new Object[] { username },new BeanPropertyRowMapper<>(UserBean.class));if (list != null && list.size() == 1) {return list.get(0);}return null;
}// 根据用户id查询用户权限
public List<String> getAuthorize(Long userId) {String sql = "SELECT * FROM user_authorize WHERE user_id =?";List<UserAuthorizeBean> list = jdbcTemplate.query(sql, new Object[] { userId },new BeanPropertyRowMapper<>(UserAuthorizeBean.class));List<String> authorizes = new ArrayList<>();list.forEach(c -> authorizes.add(c.getAuthorizeCode()));return authorizes;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
SpringDataUserDetailsService
package com.feizhou.oauth.service;
import java.util.List;
import com.feizhou.oauth.bean.UserBean;
import com.feizhou.oauth.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
/**
@author Administrator
@version 1.0
**/
@Service
public class SpringDataUserDetailsService implements UserDetailsService {@Autowired
UserDao userDao;// 根据账号查询用户信息,
// 通过@Service将SpringDataUserDetailsService注入容器,通过UserDetailsService接口表明该类的类型是UserDetailsService
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 将来连接数据库根据账号查询用户信息UserBean bean = userDao.getUserByUsername(username);if (bean == null) {// 如果用户查不到,返回null,由provider来抛出异常return null;}// 查询当前数据库的用户资源权限List<String> authorize = userDao.getAuthorize(bean.getId());String[] authorizeArr = new String[authorize.size()];authorize.toArray(authorizeArr);// 添加权限UserDetails userDetails = User.withUsername(bean.getUserName()).password(bean.getPassword()).authorities(authorizeArr).build();return userDetails;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
application.properties
spring.application.name=oauth-authorizationServer
server.port=8081
spring.datasource.url = jdbc:mysql://zhoufei.ali.db.com:3306/test?useUnicode=true
spring.datasource.username = root
spring.datasource.password = root
spring.datasource.driver-class-name = com.mysql.jdbc.Driver
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
pom.xml
<?xml version=“1.0” encoding=“UTF-8”?>
<project xmlns=“http://maven.apache.org/POM/4.0.0”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>
<parent>
<artifactId>oauth-parent</artifactId>
<groupId>oauth-learn</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>oauth-authorizationServer</artifactId><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.data</groupId><artifactId>spring-data-commons</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-security</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-jwt</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies>
</project>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
mysql.sql
数据库脚本
CREATE TABLE `user` (`id` bigint(255) NOT NULL AUTO_INCREMENT,`password` varchar(255) DEFAULT NULL,`user_name` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
CREATE TABLE user_authorize
(
id
bigint(20) NOT NULL AUTO_INCREMENT,
user_id
bigint(20) DEFAULT NULL,
authorize_code
varchar(255) DEFAULT NULL,
PRIMARY KEY (id
)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
INSERT INTO user_authorize
(id
, user_id
, authorize_code
) VALUES (1, 1, ‘admin’);
– 账号密码都是admin
INSERT INTO user
(id
, password
, user_name
) VALUES (1, ‘$2a$10$4ewqeeIzvg4rBIIvSC4QFu4DEO0xGcHetdjac4950UbOX91Jrk1we’, ‘admin’);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
3.2、解读代码
3.2.1、OAuth2.0授权服务器的开启
- 使用 @EnableAuthorizationServer注解
- 继承 AuthorizationServerConfigurerAdapter
3.2.2、AuthorizationServerConfigurerAdapter:
要配置以下几个类,通过重写以下方法来实现
3.2.3、ClientDetailsServiceConfigurer
- 用来配置客户端详情服务(ClientDetailsService)
- ClientDetailsService负责查找ClientDetails
- 客户端详情服务:第三方服务器来授权服务器申请访问资源。通过授权后,颁发clientId,secret给第三方服务器,表示第三方服务器是信任的服务器。
- 可通过内存或者数据库来配置
ClientDetails重要属性列表:
- clientId:标识客户的Id
- secret:客户端秘钥
- scope:
- 限制客户端的访问范围
- 默认空:拥有全部的访问范围。
- authorizedGrantTypes:
- 客户端可以使用的授权类型
- 默认为空
- authorities:
- 客户端可以使用的权限
- 基于SpringSecurityauthorities
ClientDetails介绍
- 能够在应用程序运行的时候进行更新
- 可以通过访问底层的存储服务
- 客户端详情存储在一个关系数据库的表中
- 实现方式
- 使用JdbcClientDetailsService
- 自己实现ClientRegistrationService接口
- 自己实现ClientDetailsService接口
具体代码
3.2.4、AuthorizationServerTokenServices
- 令牌管理服务
- 定义管理令牌的操作
- 令牌
- 用来加载身份信息
- 包含了这个令牌的相关权限。
- 这个接口的实现,则需要继承DefaultTokenServices
DefaultTokenServices
- 可以修改令牌的格式
- 可以修改令牌的存储。
- 默认:创建一个令牌使用随机值来进行填充的
- 除了持久化令牌是委托一个TokenStore接口来实现以外,这个类几乎帮你做了所有的事情。
TokenStore
- 默认实现:InMemoryTokenStore
- 所有的令牌是被保存在了内存中
- 它可以完美的工作在单服务器上(即访问并发量压力不大的情况下,并且它在失败的时候不会进行备份)
- JdbcTokenStore
- 基于JDBC的实现版本,令牌会被保存进关系型数据库
- 注意点:需要把"spring-jdbc"这个依赖加入到你的classpath当中。
- JwtTokenStore
- 它可以把令牌相关的数据进行编码(因此对于后端服务来说,它不需要进行存储,这将是一个重大优势)
- 缺点:
- 撤销一个已经授权令牌非常困难,所以它通常用来处理一个生命周期较短的令牌以及撤销刷新令牌(refresh_token)
- 这个令牌占用的空间会比较大,如果你加入了比较多用户凭证信息。JwtTokenStore不会保存任何数据,但是它在转换令牌值以及授权信息方面与DefaultTokenServices所扮演的角色是一样的。
3.2.5、AuthorizationServerEndpointsConfigurer
- 可以完成令牌服务
- 可以完成令牌endpoint配置
配置授权类型(GrantTypes)
- authenticationManager:认证管理器
- 选择密码(password)授权类型的时候,请设置这个属性注入一个AuthenticationManager对象。
- userDetailsService:
- 设置UserDetailsService接口的实现类(用户登录验证)
- 可以把这个东西设置到全局域上面去(例如GlobalAuthenticationManagerConfigurer这个配置对象),当你设置了这个之后,那么"refresh_token"即刷新令牌授权类型模式的流程中就会包含一个检查,用来确保这个账号是否仍然有效。
- authorizationCodeServices:设置授权码服务
- 用于"authorization_code"授权码类型模式
- implicitGrantService:设置隐式授权模式,用来管理隐式授权模式的状态。
- tokenGranter:
- 设置TokenGranter接口实现,授权将会交由你来完全掌控,并且会忽略掉上面的这几个属性
- 这个属性一般是用作拓展用途的,即标准的四种授权模式已经满足不了你的需求的时候,才会考虑使用这个。
具体代码
配置授权端点的URL(EndpointURLs)
- AuthorizationServerEndpointsConfigurer有一个pathMapping()的方法用来配置端点URL链接
- 它有两个参数
- 第一个参数:String类型的,这个端点URL的默认链接。
- 第二个参数:String类型的,你要进行替代的URL链接。
- 以上的参数都将以"/"字符为开始的字符串,
- 框架的默认URL链接如下列表,可以作为这个pathMapping()方法的第一个参数
- /oauth/authorize:授权端点。
- /oauth/token:令牌端点。
- /oauth/confirm_access:用户确认授权提交端点。
- /oauth/error:授权服务错误信息端点。
- /oauth/check_token:用于资源服务访问的令牌解析端点。
- /oauth/token_key:提供公有密匙的端点,如果你使用JWT令牌的话。需要注意的是授权端点这个URL应该被SpringSecurity保护起来只供授权用户访问。
3.2.6、authorizationCodeServices
授权码服务的存储方式
具体代码
3.2.7、AuthorizationServerSecurityConfigurer
- 令牌端点的安全约束
- tokenkey:/oauth/token_key端点完全公开。
- checkToken:/oauth/check_token端点完全公开。
- allowFormAuthenticationForClients:允许表单认证
具体代码
3.3、验证认证服务器
3.3.1、授权码模式
01、请求授权码
http://localhost:8081/oauth/authorize?client_id=c1&response_type=code&scope=all&redirect_uri=http://www.baidu.com
- 1
02、先让你登录(Security的原因)
02、用户授权
03、返回授权码
04、请求taken
http://localhost:8081/oauth/token?client_id=c1&client_secret=secret&grant_type=authorization_code&code=kZAlHW&redirect_uri=http://www.baidu.com
- 1
3.3.2、简化模式
http://localhost:8081/oauth/authorize?client_id=c1&response_type=token&scope=all&redirect_uri=http://www.baidu.com
- 1
3.3.3、密码模式
http://localhost:8081/oauth/token?client_id=c1&client_secret=secret&grant_type=password&username=admin&password=admin
- 1
3.3.4、客户端模式
http://localhost:8081/oauth/token?client_id=c1&client_secret=secret&grant_type=client_credentials
- 1
- 2
4、资源服务器代码:oauth-ResourceServer
4.1、代码
ResouceServerConfig
package com.feizhou.oauth.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
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.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
/**
@author Administrator
@version 1.0
**/
@Configuration
@EnableResourceServer
public class ResouceServerConfig extends ResourceServerConfigurerAdapter {// 授权服务的资源列表
public static final String RESOURCE_ID = “res1”;@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources
// 资源 id
.resourceId(RESOURCE_ID)
// 令牌服务
.tokenServices(tokenService())
.stateless(true);
}@Override
public void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/**")// 所有的访问,授权访问都要是all,和认证服务器的授权范围一一对应.access("#oauth2.hasScope('all')")//去掉防跨域攻击.and().csrf().disable()//session管理.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Bean
// 资源服务令牌解析服务
public ResourceServerTokenServices tokenService() {
// 使用远程服务请求授权服务器校验token,必须指定校验token 的url、client_id,client_secret
RemoteTokenServices service = new RemoteTokenServices();
service.setCheckTokenEndpointUrl(“http://localhost:8081/oauth/check_token”);
service.setClientId(“c1”);
service.setClientSecret(“secret”);
return service;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
ResouceServerConfig
package com.feizhou.oauth.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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
//由于Spring boot starter自动装配机制,这里无需使用@EnableWebSecurity
//@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) // 方法授权
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// 密码编码器,不加密
@Bean
public PasswordEncoder passwordEncoder() {// return NoOpPasswordEncoder.getInstance(); // 不加密return new BCryptPasswordEncoder();// BCryptPasswordEncoder加密
}// web url 拦截规则
@Override
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated()// 所有其他请求必须认证通过.and().formLogin().loginPage("/login").successForwardUrl("/login-success")// 自定义登录成功的页面地址.permitAll().and().logout().permitAll().and()// 会话管理.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);// 会话管理
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
LoginController
package com.feizhou.oauth.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
@author Administrator
@version 1.0
**/
@RestController
public class LoginController {@RequestMapping(value = “/login-success”)
public String loginSuccess() {
return getUsername() + " login-success 登录成功";
}/**
- 测试资源1
- @return
*/
@GetMapping(value = “/admin/p1”)
@PreAuthorize(“hasAuthority(‘p1’)”)//拥有p1权限才可以访问
public String r1() {
return " /admin/p1 " + getUsername() + “访问资源1”;
}
/**
- 测试资源2
- @return
*/
@GetMapping(value = “/user/p2”)
@PreAuthorize(“hasAuthority(‘p2’)”)//拥有p2权限才可以访问
public String r2() {
return "/user/p2 " + getUsername() + “访问资源2”;
}
// 获取当前用户信息
private String getUsername() {
String username = null;
// 当前认证通过的用户身份
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// 用户身份
Object principal = authentication.getPrincipal();
if (principal == null) {
username = “匿名”;
}
if (principal instanceof UserDetails) {
UserDetails userDetails = (UserDetails) principal;
username = userDetails.getUsername();
} else {
username = principal.toString();
}
return username;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
application.properties
spring.application.name=oauth-ResourceServer
server.port=8082
- 1
- 2
- 3
pom.xml
<?xml version=“1.0” encoding=“UTF-8”?>
<project xmlns=“http://maven.apache.org/POM/4.0.0”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>
<parent>
<artifactId>oauth-parent</artifactId>
<groupId>oauth-learn</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>oauth-ResourceServer</artifactId><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-security</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-oauth2</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies>
</project>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
4.2、代码解读
4.2.1、OAuth2.0资源服务器的开启
- 需要添加 @EnableResourceServer注解
- 会自动增加了一个类型为 OAuth2AuthenticationProcessingFilter 的过滤器链
- 需要 继承ResourceServerConfigurerAdapter
4.2.2、ResourceServerSecurityConfigurer
- tokenServices:
- ResourceServerTokenServices 类的实例
- 用来实现令牌服务
- tokenStore:
- TokenStore类的实例,指定令牌如何访问,与tokenServices配置可选
- resourceId
- 这个资源服务的ID,这个属性是可选的,推荐设置并在授权服务中进行验
- tokenExtractor
- 令牌提取器用来提取请求中的令牌
4.2.3、HttpSecurity配置这个与Spring Security类似
4.2.4、ResourceServerTokenServices
- DefaultTokenServices
- 授权服务和资源服务在同一个应用程序上可以使用
- 在资源服务器本地配置令牌存储、解码、解析方式使用
- RemoteTokenServices
- 资源服务器通过HTTP请求来解码令牌
- 请求端点:/oauth/check_token
4.3、测试
01、获取token
02、检查token的信息
03、admin请求可以访问的资源
04、user请求可以访问的资源(token 是admin的)
认证服务器,资源服务器相关推荐
- 扩展资源服务器解决oauth2 性能瓶颈
用户携带token 请求资源服务器 资源服务器拦截器 携带token 去认证服务器 调用tokenstore 对token 合法性校验 资源服务器拿到token,默认只会含有用户名信息 通过用户名调用 ...
- 认证服务器的搭建_SpringCloud搭建的认证中心和资源服务器的微服务项目源码分享...
本项目基于spring-cloud-starter-oauth2搭建的认证中心和资源服务器的微服务项目,项目不仅仅简单的demo,项目的出发点在于实战应用.本项目为笔者花了不少时间和精力整理出来的,只 ...
- Spring Security 0auth2 认证服务器和资源服务器实现
一,OAuth2开放授权协议/标准 OAuth(开放授权)是⼀个开放协议/标准,允许⽤户授权第三⽅应⽤访问他们存储在另外的服务提供者 上的信息,⽽不需要将⽤户名和密码提供给第三⽅应⽤或分享他们数据的所 ...
- 使用Spring Security 资源服务器来保护Spring Cloud 微服务
我在上一篇对资源服务器进行了简单的阐述,让大家对资源服务器的概念有了简单的认识,今天我将用实际例子来演示单体应用改造为Spring Cloud微服务时的资源服务器实现. 资源服务器改造 以Spring ...
- Apsara Clouder云计算专项技能认证:云服务器ECS入门[考试真题]
Apsara Clouder云计算专项技能认证:云服务器ECS入门[认证考试真题](答案仅供参考) 单选题13题 开放云服务器ECS安全组里22端口,有什么作用? A.可以远程访问数据库 B.支持ht ...
- 使用Spring Security Oauth2 和 JWT保护微服务--资源服务器的编写
编写hcnet-website的资源服务 依赖管理pom文件 hcnet-website工程的pom文件继承主maven的pom文件.在hcnet-website工程的pom文件中添加web功能的起步 ...
- 2023阿里云学生服务器权益,含Clouder认证:云服务器ECS答案
文章目录 阿里云学生权益(服务器使用7个月) 1.高校计划续费任务 - 飞天加速计划3.0(2个任务) 2.任务1:完成实验<ECS云服务器新手上路> 2.2: 续费6个月 3.任务2:A ...
- Tomcat 动态资源服务器部署及应用
Tomcat 动态资源服务器部署及应用 Java 2 EE 计数体系包含如 Serverlet , JSP , JMX 等等. 以OpenJDK为例,当前比较常用的有1.6.0.1.7.0.1.8.0 ...
- SpringSecurity(二十)---OAuth2:实现资源服务器(上)资源服务器搭建以及直接调用授权服务器模式
一. 前言 本章将讨论如何使用Spring Security实现一个资源服务器,资源服务器是管理用户资源的组件.另外,学习本章有个前提,需要先把前面搭建授权服务器的相关文章先给阅读,否则可能后面出现的 ...
最新文章
- LTE QCI分类 QoS
- 软件测试培训适合什么人学习?
- ASIC设计的一些软件
- 互联网共鸣之声:2018年或成为云计算转折之年
- windowswps怎么以文件形式发送_一个招投标项目出现了履约争议,但是没有签订合同,怎么办?...
- 响应json数据之过滤静态资源
- dj鲜生-25-用户登陆验证成功-但是没有激活的处理
- 搜索引擎的强大意味着与之合作就会双赢?
- [Windows] 程序生成出现语法错误: 意外的令牌“标识符”,预期的令牌为“类型说明符”...
- win11快捷键失效怎么处理 Windows快捷键失效的解决方法
- Python文档学习笔记(1)--使用Python 解释器
- 如何对散列查找进行asl分析计算?_Python数据结构与算法——散列(Hash)
- 各种注册序列号 用户名
- Tomcat9一介绍与部署
- 柳州铁一中机器人_柳州铁路第一中学的办学成果
- 训练记录番外篇(2):2022 ICPC Gran Premio de Mexico 2da Fecha
- recycler上下拉刷新view
- java-net-php-python-jspm现代化社区去也管理系统计算机毕业设计程序
- 脱粉之后,华为的喜忧参半
- 这么多编程学习网站,总有一个适合你吧