1.导入坐标
<!--导入spring cloud oauth2依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.1.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.4.RELEASE</version>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<!--mysql 数据库配置-->
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.19</version>
</dependency>
<dependency>
<!--数据库连接配置 -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--MP代码自动生成-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.0</version>
</dependency>
<!-- 模板引擎 -->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<!--mybatisplus-->
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>2.配置数据源
server:
port: 999
spring:
application:
name: yyjzy-cloud-oauth-server
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.1.7:3306/oauth2?useUnicode=true&characterEncoding=utf8
username: root
password: 123456
druid:
initial-size: 10
min-idle: 10
max-active: 30
max-wait: 50000
eureka:
client:
service-url:
#注册到集群,多个用逗号隔开
defaultZone: http://localhost:8761/eureka,http://localhost:8762/eureka
instance:
prefer-ip-address: true #服务实例中显示ip,而不是显示主机名(兼容老的eureka)
# 实例名称: 192.168.1.6:lagou-cloud-oauth-server:999,我们可以自定义它
instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}:@project.version@
mybatis-plus:
mapper-locations: classpath:mapper/*.xml3.token配置,接口权限配置
package com.yyj.edu.config;
import com.netflix.discovery.converters.Auto;
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.jwt.crypto.sign.MacSigner;
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.client.JdbcClientDetailsService;
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;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import javax.sql.DataSource;
@Configuration
@EnableAuthorizationServer // 开启认证服务功能
public class OauthServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
AuthenticationManager authenticationManager;
/**
* 借口权限相关的配置
* @param security
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
super.configure(security);
security
.allowFormAuthenticationForClients() // 允许客户端的表单认证
// 开启端口/oauth/token_key的访问权限
.tokenKeyAccess("permitAll()")
// 开启端口 /oauth/check_token的访问权限
.checkTokenAccess("permitAll()");
}
/**
* 客户端详情配置
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
super.configure(clients);
// 从内存中加载客户端详情
// clients.inMemory()// 存储方式 有内存 数据库等
// // 添加客户端 制定client_id
// .withClient("client_haha")
// // 访问密码
// .secret("yyjzy")
// // 资源id 这里配置完还需要在 资源服务器配置
// .resourceIds("code")
// // 认证类型/令牌办法模式
// .authorizedGrantTypes("password","refresh_token")
// .scopes("all"); // 客户端的权限范围
// 从数据库加载客户端详情
clients.withClientDetails(createJdbcClientDetailsService());
}
@Autowired
private DataSource dataSource;
@Bean
public JdbcClientDetailsService createJdbcClientDetailsService(){
JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource);
return jdbcClientDetailsService;
}
/**
* token相关的配置
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
super.configure(endpoints);
endpoints.tokenStore(tokenStore()) // 制定token的存储方式
.tokenServices(authorizationServerTokenServices()) // tokent的生成细节
.authenticationManager(authenticationManager) //制定认证管理器
.allowedTokenEndpointRequestMethods(HttpMethod.POST,HttpMethod.GET);
}
private String sign_key="haha123";
/**
* 设置token的存储方式
* @return
*/
public TokenStore tokenStore(){
//return new InMemoryTokenStore();
// 使用jwt令牌
return new JwtTokenStore(jwtAccessTokenConverter());
}
/**
* 返回jwt令牌转换器
* @return
*/
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
jwtAccessTokenConverter.setSigningKey(sign_key); // 签名秘钥
jwtAccessTokenConverter.setVerifier(new MacSigner(sign_key)); // 验证时使用的秘钥,和签名秘钥保持一致
return jwtAccessTokenConverter;
}
public AuthorizationServerTokenServices authorizationServerTokenServices(){
// 使用默认实现
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setSupportRefreshToken(true); // 是否开启令牌刷新
defaultTokenServices.setTokenStore(tokenStore());
// 针对jwt令牌的添加
defaultTokenServices.setTokenEnhancer(jwtAccessTokenConverter());
// 设置令牌有效时间
defaultTokenServices.setAccessTokenValiditySeconds(80);
// 设置刷新令牌的有效时间
defaultTokenServices.setRefreshTokenValiditySeconds(258200);
return defaultTokenServices;
}
}4.用户名 密码的校验
package com.yyj.edu.config;
import com.yyj.edu.service.impl.JdbcUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.util.ArrayList;
/**
* 该配置类 主要配置用户名 密码的校验工作
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
JdbcUserDetailsService jdbcUserDetailsService;
/**
* 注册一个认证管理器对象
* @return
* @throws Exception
*/
@Bean
public AuthenticationManager authenticationManager()throws Exception{
return super.authenticationManager();
}
/**
* 密码编码对象
* @return
*/
@Bean
public PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
@Autowired
PasswordEncoder passwordEncoder;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 从内存中获取用户名密码
// UserDetails user = new User("admin","1234567",new ArrayList<>());
// auth.inMemoryAuthentication()
// .withUser(user).passwordEncoder(passwordEncoder);
// 从数据库获取用户名密码
auth.userDetailsService(jdbcUserDetailsService).passwordEncoder(passwordEncoder);
}
}5.userdetails封装 从数据库获取用户 密码
package com.yyj.edu.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yyj.edu.mapper.UsersMapper;
import com.yyj.edu.model.UsersDo;
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;
import java.util.ArrayList;
@Service
public class JdbcUserDetailsService implements UserDetailsService {
@Autowired
UsersMapper usersMapper;
/**
* 根据username查询该用户所有信息,封装成userdetails类型对象返回
* @param userName
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
QueryWrapper<UsersDo> objectQueryWrapper = new QueryWrapper<>();
objectQueryWrapper.eq("username",userName);
UsersDo usersDo = usersMapper.selectOne(objectQueryWrapper);
User user = new User(usersDo.getUsername(),usersDo.getPassword(),new ArrayList<>());
return user;
}
}6.验证链接详解
1)生成token的链接
http://localhost:999/oauth/token?client_secret=yyjzy&grant_type=password&username=admin&password=123456&client_id=client_haha
client_secret: 设置的访问的密码
grant_type:认证类型
username:用户名
password: 访问密码
client_id: 客户端id2) 检查token的链接
http://localhost:999/oauth/check_token?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicmVzdW1lIiwiYXV0b2RlbGl2ZXIiXSwiZXhwIjoxNjEyNzkxNjU3LCJ1c2VyX25hbWUiOiJhZG1pbiIsImp0aSI6IjIyODg1YzQxLTFiNGMtNDA3NS05ZTQzLTUxZGI2NGI5YzYzNyIsImNsaWVudF9pZCI6ImNsaWVudF9sYWdvdTEyMyIsInNjb3BlIjpbImFsbCJdfQ.hv2jjvEgAVDpz-42xCUF5XZN1CXKXwolBRUOZkqLvSk3)刷新token的链接
http://localhost:999/oauth/token?client_secret=yyjzy&grant_type=refresh_token&client_id=client_haha&refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicmVzdW1lIiwiYXV0b2RlbGl2ZXIiXSwidXNlcl9uYW1lIjoiYWRtaW4iLCJzY29wZSI6WyJhbGwiXSwiYXRpIjoiMjI4ODVjNDEtMWI0Yy00MDc1LTllNDMtNTFkYjY0YjljNjM3IiwiZXhwIjoxNjEzMDQ5Nzc3LCJqdGkiOiI4OTE1MmM1Zi03MjRlLTRhZjEtYjBjNi03YTdmZjA2OTI0ZjciLCJjbGllbnRfaWQiOiJjbGllbnRfbGFnb3UxMjMifQ.CVbO9P4J34f-95FhFj6WnIgAaFnwQOlB-HnIE5QK9KQ7.数据库的表
1)Oauth2客户端信息表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for oauth_client_details
-- ----------------------------
DROP TABLE IF EXISTS `oauth_client_details`;
CREATE TABLE `oauth_client_details` (
`client_id` varchar(48) NOT NULL,
`resource_ids` varchar(256) DEFAULT NULL,
`client_secret` varchar(256) DEFAULT NULL,
`scope` varchar(256) DEFAULT NULL,
`authorized_grant_types` varchar(256) DEFAULT NULL,
`web_server_redirect_uri` varchar(256) DEFAULT NULL,
`authorities` varchar(256) DEFAULT NULL,
`access_token_validity` int(11) DEFAULT NULL,
`refresh_token_validity` int(11) DEFAULT NULL,
`additional_information` varchar(4096) DEFAULT NULL,
`autoapprove` varchar(256) DEFAULT NULL,
PRIMARY KEY (`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of oauth_client_details
-- ----------------------------
BEGIN;
INSERT INTO `oauth_client_details` VALUES ('client_haha',
'autodeliver,resume', 'yyjzy', 'all', 'password,refresh_token',
NULL, NULL, 7200, 259200, NULL, NULL);
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;2)验证⽤户合法性表
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` char(10) DEFAULT NULL,
`password` char(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of users
-- ----------------------------
BEGIN;
INSERT INTO `users` VALUES (4, 'admin', '123456');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;8.在资源服务器,也就是要访问认证服务的客户端添加配置
package com.yyj.edu.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.jwt.crypto.sign.MacSigner;
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.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
@Configuration
@EnableResourceServer
@EnableWebSecurity
public class ResourceServerConfiger extends ResourceServerConfigurerAdapter {
/**
* 该方法用于定义资源服务器向远程认证服务器发起请求,进行token校验等事宜
* @param resources
* @throws Exception
*/
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
// // 设置当前资源服务的资源id
// resources.resourceId("code");
// // 定义token服务对象
// RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
// // 校验端点/接口设置
// remoteTokenServices.setCheckTokenEndpointUrl("http://localhost:999/oauth/check_token");
// // 携带客户端id和安全码
// remoteTokenServices.setClientId("client_lagou");
// remoteTokenServices.setClientSecret("yyjzy");
// resources.tokenServices(remoteTokenServices)
// jwt令牌改造
resources.resourceId("autodeliver").tokenStore(tokenStore()).stateless(true); // 无状态设置
}
/**
* 设置白名单
* @param http
* @throws Exception
*/
@Override
public void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.authorizeRequests()
.antMatchers("/yyjzy/**").authenticated()
.anyRequest().permitAll(); // 其他请求不认证
}
private String sign_key="haha123";
/**
* 设置token的存储方式
* @return
*/
public TokenStore tokenStore(){
//return new InMemoryTokenStore();
// 使用jwt令牌
return new JwtTokenStore(jwtAccessTokenConverter());
}
/**
* 返回jwt令牌转换器
* @return
*/
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
jwtAccessTokenConverter.setSigningKey(sign_key); // 签名秘钥
jwtAccessTokenConverter.setVerifier(new MacSigner(sign_key)); // 验证时使用的秘钥,和签名秘钥保持一致
return jwtAccessTokenConverter;
}
}
















