1、认证中心
1.1 依赖
<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>com.mine</groupId>
<artifactId>oauth2.0-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<!-- 管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- springboot整合freemarker -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-->spring-boot 整合security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- spring-cloud-starter-oauth2 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
</dependencies>
<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
1.2 springsecurity引入
SecurityConfig
package com.mine.config;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.stereotype.Component;
@Component
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("user")
.password(new BCryptPasswordEncoder().encode("123456")).authorities("ROLE");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().formLogin();
}
}
1.3 认证中心配置
MyAuthenticationManager
package com.mine.config;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.stereotype.Component;
@Component
public class MyAuthenticationManager implements AuthenticationManager {
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
UserDetailsService userDetailsService = new InMemoryUserDetailsManager();
((InMemoryUserDetailsManager) userDetailsService).createUser(User.withUsername("zhangsan")
.password(new BCryptPasswordEncoder().encode("123456")).authorities("ROLE_USER").build());
daoAuthenticationProvider.setUserDetailsService(userDetailsService);
daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
daoAuthenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder());
return daoAuthenticationProvider.authenticate(authentication);
}
}
AuthorizationServerConfig
package com.mine.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.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
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;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
// accessToken有效期
private static int ACCESS_TOKEN_VALIDITY_SECONDS = 7200;
// refreshToken有效期
private static int REFRESH_TOKEN_VALIDITY_SECONDS = 7200;
@Autowired
private MyAuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("elapse").secret(new BCryptPasswordEncoder().encode("123456"))
.redirectUris("https://www.baidu.com")
.authorizedGrantTypes("authorization_code", "client_credentials", "refresh_token", "password",
"implicit")
.scopes("all").accessTokenValiditySeconds(ACCESS_TOKEN_VALIDITY_SECONDS)
.refreshTokenValiditySeconds(REFRESH_TOKEN_VALIDITY_SECONDS);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager).allowedTokenEndpointRequestMethods(HttpMethod.GET,
HttpMethod.POST);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()").checkTokenAccess("permitAll()").allowFormAuthenticationForClients();
}
@Bean
public PasswordEncoder passwordEncoder() {
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
return passwordEncoder;
}
}
1.4 启动类
AppOauthServer
package com.mine;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AppOauthServer {
public static void main(String[] args) {
SpringApplication.run(AppOauthServer.class, args);
}
}
2、资源服务器
2.1 依赖
<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>com.mine</groupId>
<artifactId>oauth2.0-order</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<!-- 管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- SpringBoot整合Web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- springboot整合freemarker -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-->spring-boot 整合security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
</dependencies>
<!-- 注意: 这里必须要添加, 否者各种依赖有问题 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
2.2 配置文件
application.yml
server:
port: 8081
security:
oauth2:
resource:
####从认证授权中心上验证token
tokenInfoUri: http://localhost:8080/oauth/check_token
preferTokenInfo: true
client:
accessTokenUri: http://localhost:8080/oauth/token
userAuthorizationUri: http://localhost:8080/oauth/authorize
###appid
clientId: elapse
###appSecret
clientSecret: 123456
2.3 资源服务器配置
ResourceServerConfiguration
package com.mine.config;
import org.springframework.context.annotation.Configuration;
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;
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
// 对 api/order 请求进行拦截
http.authorizeRequests().antMatchers("/api/order/**").authenticated();
}
}
2.4 控制器
OrderController
package com.mine.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/order")
public class OrderController {
@RequestMapping("/getOrder")
public String getOrder() {
return "i am order resource";
}
}
2.5 启动类
AppResourceOrder
package com.mine;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
@SpringBootApplication
@EnableOAuth2Sso
public class AppResourceOrder {
public static void main(String[] args) {
SpringApplication.run(AppResourceOrder.class, args);
}
}
3、测试
3.1 启动认证中心与资源中心
3.2 尝试直接访问资源中心地址
localhost:8081/api/order/getOrder
响应
{
"error": "unauthorized",
"error_description": "Full authentication is required to access this resource"
}
3.3 通过认证中心请求资源
3.3.1 获取授权码(浏览器访问)(登录用户名user,密码123456)
http://localhost:8080/oauth/authorize?response_type=code&client_id=elapse&redirect_uri=https://www.baidu.com
用户选择授权后,跳转到回调地址,例如
https://www.baidu.com/?code=r1uh2E
3.3.2 根据授权码获取令牌(postman调用)(授权码只能用一次)
http://localhost:8080/oauth/token?grant_type=authorization_code&code=r1uh2E&redirect_uri=https://www.baidu.com&client_id=elapse&client_secret=123456&scope=all
响应
{
"access_token": "63ec445e-3f14-4c2c-97fa-434100aa6a8f",
"token_type": "bearer",
"refresh_token": "4d67d9ff-c3a1-43a4-b7cb-cdcfad714a2b",
"expires_in": 7199,
"scope": "all"
}
3.3.3 根据获取到的令牌(accessToken)访问资源(postman调用)
localhost:8081/api/order/getOrder
下面2选1
1、设置认证信息,设置相应方式为oauth2,输入Access Token
2、设置请求头信息,key为Authorization,value为Bearer+空格+令牌
响应
i am order resource
3.4 密码认证方式获取令牌
3.4.1 密码方式获取令牌(postman调用)
http://localhost:8080/oauth/token
post请求,参数如下:
grant_type:password
username:zhangsan
password:123456
client_id:elapse
client_secret:123456
scope:all
相应
{
"access_token": "17493e77-f30e-495b-b922-6df5090d891a",
"token_type": "bearer",
"refresh_token": "aaeef695-c22f-49df-b612-a0a22cde2714",
"expires_in": 7188,
"scope": "all"
}