前提
* JDK1.8
* SpringCloud Greenwich.RELEASE
* SpringBoot 2.1.8.RELEASE
注
先看一下项目结构
现在开始搭建,首先建立一个maven项目,即父maven工程,pom文件内容如下
spring-boot-starter-parent
org.springframework.boot
2.1.8.RELEASE
UTF-8
UTF-8
1.8
8.0.16
pom
org.springframework.cloud
spring-cloud-dependencies
Greenwich.RELEASE
pom
import
javax.servlet
javax.servlet-api
3.1.0
provided
com.alibaba
fastjson
1.2.54
org.projectlombok
lombok
1.18.10
mysql
mysql-connector-java
8.0.18
org.springframework.security
spring-security-jwt
1.0.11.RELEASE
org.springframework.security.oauth.boot
spring-security-oauth2-autoconfigure
2.0.1.RELEASE
mysql
mysql-connector-java
${mysql.version}
runtime
com.alibaba
druid
1.1.3
com.baomidou
mybatis-plus-boot-starter
3.2.0
com.baomidou
mybatis-plus-generator
3.2.0
io.springfox
springfox-swagger2
2.7.0
io.springfox
springfox-swagger-ui
2.7.0
com.alibaba
fastjson
org.projectlombok
lombok
log4j
log4j
1.2.17
org.springframework.boot
spring-boot-starter-actuator
此处引入了基本都需要使用的依赖,并使用dependencyManagement 固定使用依赖的版本
下面开始搭建授权服务
新建springBoot工程,pom如下,指定父pom为上面的文件,并引入auth需要的jar包,
com.tz
spring-cloud
1.0-SNAPSHOT
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-freemarker
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
com.netflix.hystrix
hystrix-javanica
org.springframework.cloud
spring-cloud-starter-netflix-ribbon
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.retry
spring-retry
org.springframework.data
spring-data-commons
org.springframework.cloud
spring-cloud-starter-security
org.springframework.cloud
spring-cloud-starter-oauth2
org.springframework.security
spring-security-jwt
javax.interceptor
javax.interceptor-api
1.2
配置AuthorizationServer
@Configuration
@EnableAuthorizationServer
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
/**
* 令牌存储
*/
@Autowired
private TokenStore tokenStore;
/**
* 客户端管理
*/
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private AuthorizationCodeServices authorizationCodeServices;
@Autowired
private AuthenticationManager authenticationManager;
/**
* A 配置客户端详情,支持哪些客户端
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
// 客户端id
.withClient("c1")
// 客户端密钥
.secret(new BCryptPasswordEncoder().encode("secret"))
// 资源列表
.resourceIds("res1")
// 该client允许的授权类型,
.authorizedGrantTypes("authorization_code","password","client_credentials",
"implicit","refresh_token")
// 允许的授权范围,就是一个标识,read,write
.scopes("all")
.autoApprove(false)
// 验证回调地址
.redirectUris("http://www.baidu.com");
}
/**
* B 令牌访问端点,即url
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
// 密码模式需要
.authenticationManager(authenticationManager)
// 授权码模式需要
.authorizationCodeServices(authorizationCodeServices)
// 令牌管理服务
.tokenServices(tokenServices())
//允许post提交
.allowedTokenEndpointRequestMethods(HttpMethod.POST);
}
/**
* C 配置令牌端点 安全约束
* @param security
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security
// /oauth/token_key url 公开
.tokenKeyAccess("permitAll()")
// /oauth/check_token 公开
.checkTokenAccess("permitAll()")
// 表单验证,申请令牌
.allowFormAuthenticationForClients();
}
/**
* D 定义tokenServices
* @return
*/
@Bean
public AuthorizationServerTokenServices tokenServices(){
DefaultTokenServices services = new DefaultTokenServices();
services.setClientDetailsService(clientDetailsService);
services.setSupportRefreshToken(true);
services.setTokenStore(tokenStore);
// 令牌默认有限期2小时
services.setAccessTokenValiditySeconds(7200);
// 刷新令牌默认有限期3天
services.setRefreshTokenValiditySeconds(259200);
return services;
}
/**
* 设置授权码如何存储
* @param
* @return
*/
@Bean
public AuthorizationCodeServices authorizationCodeServices() {
return new InMemoryAuthorizationCodeServices();
}
}
定义令牌存储方式,TokenConfig
@Configuration
public class TokenConfig {
/**
* 令牌存储测试
*/
@Bean
public TokenStore tokenStore(){
// 内存方式,普通令牌
return new InMemoryTokenStore();
}
}
定义web配置,配置拦截url
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 认证管理器
* @return
* @throws Exception
*/
@Bean
@Override
public AuthenticationManager authenticationManager() throws Exception{
return super.authenticationManager();
}
/**
* 密码编码器
* @return
*/
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
/**
* D 安全拦截机制
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
// 关闭csrf
http.csrf().disable()
// 开启验证
.authorizeRequests()
// 访问/r/r1需要p1
.antMatchers("/r/r1").hasAnyAuthority("p1")
// login* 不需要拦截
.antMatchers("/login*").permitAll()
// 其他的url都需要拦截
.anyRequest().authenticated()
.and()
// 支持表单登录
.formLogin();
}
}
application.properties
因为引入了数据源,所以此处需要配置,但是此时没有用到,后续用到时使用
spring.application.name=oauth-server
server.port=8762
spring.main.allow-bean-definition-overriding=true
logging.level.root = info
loggin.level.org.springframework.web = info
server.servlet.context-path=/oauth
# 数据源配置 start
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud-oauth2?useUnicode=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#durid登陆账号密码
loginUsername=root
loginPassword=root
# 下面为连接池的补充设置,应用到上面所有数据源中
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙,防止sql注入
spring.datasource.filters=stat,wall,log4j
spring.datasource.logSlowSql=true
# 数据源配置end
eureka.client.enabled=false
eureka.client.allow-redirects=false
eureka.client.serviceUrl.defaultZone = http://localhost:8761/eureka/
eureka.instance.preferIpAddress = true
eureka.instance.instance-id = ${spring.application.name}:${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}}
management.endpoints.web.exposure.include=refresh,health,info,env
feign.hystrix.enabled=true
feign.compression.request.enabled=true
feign.compression.request.mime-types[0]=text/html
feign.compression.request.mime-types[1]=application/xml
feign.compression.request.mime-types[2]=application/json
feign.compression.request.min-request-size=2048
feign.compression.response.enabled=true
#mybatis-plus配置控制台打印完整带参数SQL语句
#mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
security.oauth2.client.access-token-uri=http://localhost:8762/auth/oauth/token
security.oauth2.client.user-authorization-uri=http://localhost:8762/auth/oauth/authorize
security.oauth2.client.authorized-grant-types=authorization_code
security.oauth2.resource.user-info-uri=http://localhost:8780/dashboard/user
客户端模式,post 请求获取token
http://127.0.0.1:8762/oauth/oauth/token?client_id=c1&client_secret=secret&grant_type=client_credentials
返回结果如下
用户名密码模式
定义userDetailService
@Service
@Slf4j
public class MyUserDetailService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 用户名tz,密码123
UserDetails userDetails = User.withUsername("tz").password("$2a$10$pTffBwh9mawjeGG9K5ZhbenBfWQRV1aFVgZqVt59eM67iJhDqARyG").authorities("p1").build();
return userDetails;
}
加密的密码生成,生成的密码每次都不一样,但是都代表123
@Test
public void createBCryptPw(){
String gensalt = BCrypt.gensalt();
System.out.println(gensalt);
String hashpw = BCrypt.hashpw("123", gensalt);
System.out.println(hashpw);
}
用户名密码 post 请求,会返回refresh_token
http://127.0.0.1:8762/oauth/oauth/token?client_id=c1&client_secret=secret&username=tz&password=123&grant_type=password
返回结果
好了,授权服务器简单模式搭建完成,详细点击原文链接查看README,欢迎继续关注下一篇客户资源服务器搭建