1.创建父工程
<groupId>com.itheima</groupId> <artifactId>springboot_security_oauth</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> </parent> <properties> <spring-cloud.version>Greenwich.RELEASE</spring-cloud.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <repositories> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
2.创建资源模块
2.1 创建工程并导入依赖
<parent> <artifactId>springboot_security_oauth</artifactId> <groupId>com.itheima</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>oauth_source</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <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> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency> </dependencies>
2.2 创建配置文件
server: port: 9002 spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql:///security_authority username: root password: root main: allow-bean-definition-overriding: true mybatis: type-aliases-package: com.itheima.domain configuration: map-underscore-to-camel-case: true logging: level: com.itheima: debug
2.3 创建启动类
@SpringBootApplication @MapperScan("com.itheima.mapper") public class OAuthSourceApplication { public static void main(String[] args) { SpringApplication.run(OAuthSourceApplication.class, args); } }
2.4 创建处理器
@RestController @RequestMapping("/product") public class ProductController { @GetMapping public String findAll(){ return "查询产品列表成功!"; } }
3.创建授权模块
3.1 创建工程并导入依赖
<parent> <artifactId>springboot_security_oauth</artifactId> <groupId>com.itheima</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>oauth_server</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <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> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.0</version> </dependency> </dependencies>
3.2 创建配置文件
server: port: 9001 spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql:///security_authority username: root password: root main: allow-bean-definition-overriding: true # 这个表示允许我们覆盖OAuth2放在容器中的bean对象,一定要配置 mybatis: type-aliases-package: com.itheima.domain configuration: map-underscore-to-camel-case: true logging: level: com.itheima: debug
3.3 创建启动类
@SpringBootApplication @MapperScan("com.itheima.mapper") public class OauthServerApplication { public static void main(String[] args) { SpringApplication.run(OauthServerApplication.class, args); } }
3.4 创建配置类
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService myCustomUserService; @Bean public BCryptPasswordEncoder myPasswordEncoder(){ return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() //所有资源必须授权后访问 .anyRequest().authenticated() .and() .formLogin() .loginProcessingUrl("/login") .permitAll()//指定认证页面可以匿名访问 //关闭跨站请求防护 .and().csrf().disable(); } @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { //UserDetailsService类 auth.userDetailsService(myCustomUserService) //加密策略 .passwordEncoder(myPasswordEncoder()); } //AuthenticationManager对象在OAuth2认证服务中要使用,提取放入IOC容器中 @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } }
3.5 创建OAuth2授权配置类
@Configuration @EnableAuthorizationServer public class OauthServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private DataSource dataSource; @Autowired private AuthenticationManager authenticationManager; @Autowired private UserDetailsService userDetailsService; //从数据库中查询出客户端信息 @Bean public JdbcClientDetailsService clientDetailsService() { return new JdbcClientDetailsService(dataSource); } //token保存策略 @Bean public TokenStore tokenStore() { return new JdbcTokenStore(dataSource); } //授权信息保存策略 @Bean public ApprovalStore approvalStore() { return new JdbcApprovalStore(dataSource); } //授权码模式专用对象 @Bean public AuthorizationCodeServices authorizationCodeServices() { return new JdbcAuthorizationCodeServices(dataSource); } //指定客户端登录信息来源 @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.withClientDetails(clientDetailsService()); } @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.allowFormAuthenticationForClients(); oauthServer.checkTokenAccess("isAuthenticated()"); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints .approvalStore(approvalStore()) .authenticationManager(authenticationManager) .authorizationCodeServices(authorizationCodeServices()) .tokenStore(tokenStore()); } }
4.测试
4.1 授权码模式测试
在地址栏访问地址
http://localhost:9001/oauth/authorize?response_type=code&client_id=heima_one
跳转到SpringSecurity默认认证页面,提示用户登录个人账户【这里是sys_user表中的数据】
登录成功后询问用户是否给予操作资源的权限,具体给什么权限。Approve是授权,Deny是拒绝。
这里我们选择read和write都给予Approve。
点击Authorize后跳转到回调地址并获取授权码
使用授权码到服务器申请通行令牌token
重启资源服务器,然后携带通行令牌再次去访问资源服务器,大功告成!
4.2 简化模式测试
在地址栏访问地址
http://localhost:9001/oauth/authorize?response_type=token&client_id=heima_one
由于上面用户已经登录过了,所以无需再次登录,其实和上面是有登录步骤的,这时,浏览器直接返回了token
直接访问资源服务器
4.3 密码模式测试
申请token
访问资源服务器
4.4 客户端模式测试
申请token
访问资源服务