oauth2基本概念 1.什么是oauth2
OAuth2.0介绍 OAuth(Open Authorization)是一个关于授权(authorization)的开放网络标准,允许用户授权第三方 应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他 们数据的所有内容。OAuth在全世界得到广泛应用,目前的版本是2.0版。
OAuth协议:https://tools.ietf.org/html/rfc6749 协议特点:简单:不管是OAuth服务提供者还是应用开发者,都很易于理解与使用; 安全:没有涉及到用户密钥等信息,更安全更灵活; 开放:任何服务提供商都可以实现OAuth,任何软件开发商都可以使用OAuth;
2.为什么用oauth2 业务系统 需要实现几种登录形式
原生app授权 app登录请求后台接口,为了安全认证,所有请求都带token信息,如果登录验证、 请求后台数据。
前后端分离单页面应用:前后端分离框架,前端请求后台数据,需要进行oauth2安全认证,比如 使用vue、react后者h5开发的app
第三方应用授权登录,比如QQ,微博,微信的授权登录。
3.怎么用oauth2 看代码
4.oauth中的角色 OAuth 定义了四个角色:
4.1 Resource owner 资源拥有者(用户)
能够授予对受保护资源的访问权限的实体。当资源所有者是一个人时,它被称为最终用户
Resource Server 资源服务器
托管受保护资源的服务器,能够使用访问令牌接受和响应受保护资源请求
Client 客户端
代表资源所有者并经其授权发出受保护资源请求的应用程序。“客户”一词确实 不暗示任何特定的实现特征(例如, 应用程序是否在服务器、桌面或其他 设备上执行)。
Authorization server 授权服务器
服务器在成功 验证资源所有者并获得授权后向客户端颁发访问令牌。授权服务器和资源服务器之间的交互超出了本规范的范围。授权服务器 可以是与资源服务器相同的服务器,也可以是单独的实体。 单个授权服务器可以发布多个资源服务器接受的访问令牌。
5.认证流程参考
6.Oauth2 的四种认证模式的流程 6.1 Authorization Code (授权码模式) 应用场景 这种方式是最常用的流程,安全性也最高,它适用于那些有后端的 Web 应用。授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏
流程
1:用户访问页面 2:访问的页面将请求重定向到认证服务器 3:认证服务器向用户展示授权页面,等待用户授权 4:用户授权,认证服务器生成一个code和带上client_id发送给应用服务器,然后,应用服务器拿到code,并用client_id去后台查询对应的client_secret 5:将code、client_id、client_secret传给认证服务器换取access_token和refresh_token 6:将access_token和refresh_token传给应用服务器 7:验证token,访问真正的资源页面
6.2 Resource Owner Password Credentials Grant(密码模式) 应用场景 如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为”密码式”(password)
流程
1:用户访问用页面时,输入第三方认证所需要的信息(QQ/微信账号密码) 2:应用页面那种这个信息去认证服务器授权 3:认证服务器授权通过,拿到token,访问真正的资源页面
6.3 Implicit Grant (隐式授权模式) 应用场景 有些 Web 应用是纯前端应用,没有后端。这时就不能用上面的方式了,必须将令牌储存在前端。RFC 6749 就规定了第二种方式,允许直接向前端颁发令牌。这种方式没有授权码这个中间步骤,所以称为(授权码)“隐藏式”(implicit)
流程
1:用户访问页面时,重定向到认证服务器。 2:认证服务器给用户一个认证页面,等待用户授权。 3:用户授权,认证服务器想应用页面返回Token 4:验证Token,访问真正的资源页面
6.4 Client Credentials Grant (客户端凭证模式) 应用场景 适用于没有前端的命令行应用,即在命令行下请求令牌
流程
1:用户访问应用客户端 2:通过客户端定义的验证方法,拿到token,无需授权 3:访问资源服务器A 4:拿到一次token就可以畅通无阻的访问其他的资源页面,如果你高度信任某个应用,RFC 6749 也允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌,这种方式称为”密码式”(password)
7.刷新token原理
8.整合(代码部分,可以跳过) gitee地址:https://gitee.com/cactuscode/springboot-oauth2.0.git
SpringBoot 2.7 + maven 3.X + JDK 1.8 + MySQL 5.7
8.1MySQL部分 oauth_access_token.sql 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 SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0 ;DROP TABLE IF EXISTS `oauth_access_token`;CREATE TABLE `oauth_access_token` ( `token_id` varchar (256 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `token` blob NULL , `authentication_id` varchar (250 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `user_name` varchar (256 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `client_id` varchar (256 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `authentication` blob NULL , `refresh_token` varchar (256 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , PRIMARY KEY (`authentication_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC ;SET FOREIGN_KEY_CHECKS = 1 ;
oauth_client_details.sql 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 SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0 ;DROP TABLE IF EXISTS `oauth_client_details`;CREATE TABLE `oauth_client_details` ( `client_id` varchar (250 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL , `resource_ids` varchar (256 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `client_secret` varchar (256 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `scope ` varchar (256 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `authorized_grant_types` varchar (256 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `web_server_redirect_uri` varchar (256 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `authorities` varchar (256 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `access_token_validity` int (11 ) NULL DEFAULT NULL , `refresh_token_validity` int (11 ) NULL DEFAULT NULL , `additional_information` varchar (4096 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `autoapprove` varchar (256 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , PRIMARY KEY (`client_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC ;INSERT INTO `oauth_client_details` VALUES ('client' , '' , '$2a$10$vtOTvQNvYfgHZjh1qYEeDOp4KOWRP9Q5Po2vPuv.ZiAEzxP7xqGZm' , 'read,write' , 'password,refresh_token' , '' , 'ROLE_ADMIN,ROLE_USER' , 7200 , 7200 , '{}' , '' );INSERT INTO `oauth_client_details` VALUES ('client_1' , '' , '$2a$10$vtOTvQNvYfgHZjh1qYEeDOp4KOWRP9Q5Po2vPuv.ZiAEzxP7xqGZm' , 'read,write' , 'client_credentials' , '' , '' , 7200 , 7200 , '{}' , '' );SET FOREIGN_KEY_CHECKS = 1 ;
oauth_refresh_token.sql 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 SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0 ;DROP TABLE IF EXISTS `oauth_refresh_token`;CREATE TABLE `oauth_refresh_token` ( `token_id` varchar (256 ) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL , `token` blob NULL , `authentication` blob NULL ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC ;SET FOREIGN_KEY_CHECKS = 1 ;
userinfo.sql 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 SET NAMES utf8mb4;SET FOREIGN_KEY_CHECKS = 0 ;DROP TABLE IF EXISTS `userinfo`;CREATE TABLE `userinfo` ( `user_id` int (11 ) NOT NULL , `user_name` varchar (255 ) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL , `password` varchar (255 ) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL , PRIMARY KEY (`user_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic ;INSERT INTO `userinfo` VALUES (1 , 'admin' , '$2a$10$qmVzBdt8AUAKzc.lGb8gbuOeh.LIF.52.d6yTzdq9ICgcAiUhuGEa' );INSERT INTO `userinfo` VALUES (2 , 'cqc' , '$2a$10$DrXszvRHzT/fLCw2nznSluxybk50Mnu/UzqY/.n5JxhVZqm0T7YNe' );SET FOREIGN_KEY_CHECKS = 1 ;
代码工程
pom.xml 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 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-security</artifactId > </dependency > <dependency > <groupId > org.springframework.security.oauth</groupId > <artifactId > spring-security-oauth2</artifactId > <version > 2.5.2.RELEASE</version > </dependency > <dependency > <groupId > org.springframework.security</groupId > <artifactId > spring-security-jwt</artifactId > <version > 1.1.1.RELEASE</version > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-web</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-devtools</artifactId > <scope > runtime</scope > <optional > true</optional > </dependency > <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <optional > true</optional > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-test</artifactId > <scope > test</scope > </dependency > <dependency > <groupId > org.springframework.security</groupId > <artifactId > spring-security-test</artifactId > <scope > test</scope > </dependency > <dependency > <groupId > com.baomidou</groupId > <artifactId > mybatis-plus-boot-starter</artifactId > <version > 3.5.3.2</version > </dependency > <dependency > <groupId > com.mysql</groupId > <artifactId > mysql-connector-j</artifactId > </dependency > <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-jdbc</artifactId > </dependency >
application.yml 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 server: port: 8001 spring: datasource: url: jdbc:mysql://192.168.55.101:3306/cqc?characterEncoding=utf-8&autoReconnect=true&useSSL=false username: root password: Gmmysql_300098 driver-class-name: com.mysql.cj.jdbc.Driver hikari: minimum-idle: 5 idle-timeout: 600000 maximum-pool-size: 10 auto-commit: true pool-name: MyHikariCP max-lifetime: 1800000 connection-timeout: 30000 connection-test-query: SELECT 1 mybatis-plus: mapper-locations: classpath:mapper/*.xml logging: level: com.com.cactus.auth2.mapper: debug
UserInfo 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 package com.cactus.auth2.entity;import com.baomidou.mybatisplus.annotation.TableField;import com.baomidou.mybatisplus.annotation.TableId;import com.baomidou.mybatisplus.annotation.TableName;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.userdetails.UserDetails;import java.util.ArrayList;import java.util.Collection;@Data @AllArgsConstructor @NoArgsConstructor @TableName("userinfo") public class UserInfo implements UserDetails { @TableId @TableField("user_id") private Integer userId; @TableField("user_name") private String userName; @TableField("password") private String password; @Override public Collection<? extends GrantedAuthority > getAuthorities() { return null ; } @Override public String getPassword () { return this .password; } @Override public String getUsername () { return this .userName; } @Override public boolean isAccountNonExpired () { return true ; } @Override public boolean isAccountNonLocked () { return true ; } @Override public boolean isCredentialsNonExpired () { return true ; } @Override public boolean isEnabled () { return true ; } }
UserMapper 1 2 3 4 5 6 7 8 9 10 11 package com.cactus.auth2.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.cactus.auth2.entity.UserInfo;import org.apache.ibatis.annotations.Mapper;@Mapper public interface UserMapper extends BaseMapper <UserInfo> { }
UserAuthService 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 package com.cactus.auth2.service;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.cactus.auth2.entity.UserInfo;import com.cactus.auth2.mapper.UserMapper;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.stereotype.Component; @Component public class UserAuthService implements UserDetailsService { @Autowired private UserMapper userMapper; @Override public UserDetails loadUserByUsername (String username) throws UsernameNotFoundException { QueryWrapper<UserInfo> queryWrapper = new QueryWrapper <>(); QueryWrapper<UserInfo> eq = queryWrapper.eq("user_name" , username); UserInfo user = userMapper.selectOne(eq); if (user == null ){ throw new UsernameNotFoundException ("not found the user:" +username); }else { return user; } } }
CustomOauthExceptionSerializer 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 package com.cactus.auth2.exception;import com.fasterxml.jackson.core.JsonGenerator;import com.fasterxml.jackson.databind.SerializerProvider;import com.fasterxml.jackson.databind.ser.std.StdSerializer;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import javax.servlet.http.HttpServletRequest;import java.io.IOException;import java.util.Date;import java.util.Map;public class CustomOauthExceptionSerializer extends StdSerializer <CustomOauthException> { private static final long serialVersionUID = 1478842053473472921L ; public CustomOauthExceptionSerializer () { super (CustomOauthException.class); } @Override public void serialize (CustomOauthException value, JsonGenerator gen, SerializerProvider provider) throws IOException { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); gen.writeStartObject(); gen.writeStringField("error" , String.valueOf(value.getHttpErrorCode())); gen.writeStringField("message" , "用户名或密码错误" ); gen.writeStringField("path" , request.getServletPath()); gen.writeStringField("timestamp" , String.valueOf(new Date ().getTime())); if (value.getAdditionalInformation()!=null ) { for (Map.Entry<String, String> entry : value.getAdditionalInformation().entrySet()) { String key = entry.getKey(); String add = entry.getValue(); gen.writeStringField(key, add); } } gen.writeEndObject(); } }
CustomOauthException 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.cactus.auth2.exception;import com.fasterxml.jackson.databind.annotation.JsonSerialize;import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;@JsonSerialize(using = CustomOauthExceptionSerializer.class) public class CustomOauthException extends OAuth2Exception { public CustomOauthException (String msg) { super (msg); } }
AuthExceptionEntryPoint 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 package com.cactus.auth2.config;import com.fasterxml.jackson.databind.ObjectMapper;import org.springframework.security.core.AuthenticationException;import org.springframework.security.web.AuthenticationEntryPoint;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.Date;import java.util.HashMap;import java.util.Map;public class AuthExceptionEntryPoint implements AuthenticationEntryPoint { @Override public void commence (HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws ServletException { Map<String, Object> map = new HashMap <>(); map.put("error" , HttpServletResponse.SC_UNAUTHORIZED); map.put("message" , authException.getMessage()); map.put("path" , request.getServletPath()); map.put("timestamp" , String.valueOf(new Date ().getTime())); response.setContentType("application/json" ); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); try { ObjectMapper mapper = new ObjectMapper (); mapper.writeValue(response.getOutputStream(), map); } catch (Exception e) { throw new ServletException (); } } }
AuthorizationServerConfig 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 package com.cactus.auth2.config;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.core.userdetails.UserDetailsService;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.token.TokenStore;import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;import javax.sql.DataSource;@Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired @Qualifier("authenticationManagerBean") private AuthenticationManager authenticationManager; @Autowired @Qualifier("dataSource") private DataSource dataSource; @Autowired private UserDetailsService userDetailsService; @Bean public TokenStore tokenStore () { return new JdbcTokenStore (dataSource); } @Override public void configure (ClientDetailsServiceConfigurer clients) throws Exception { clients.jdbc(dataSource); } @Override public void configure (AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.tokenStore(tokenStore()) .authenticationManager(authenticationManager) .userDetailsService(userDetailsService); } @Override public void configure (AuthorizationServerSecurityConfigurer security) throws Exception { security .tokenKeyAccess("permitAll()" ) .checkTokenAccess("isAuthenticated()" ) .allowFormAuthenticationForClients(); } }
CustomWebResponseExceptionTranslator 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 package com.cactus.auth2.config;import com.cactus.auth2.exception.CustomOauthException;import org.springframework.http.ResponseEntity;import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;import org.springframework.stereotype.Component;@Component public class CustomWebResponseExceptionTranslator implements WebResponseExceptionTranslator { @Override public ResponseEntity<OAuth2Exception> translate (Exception e) throws Exception { OAuth2Exception oAuth2Exception = (OAuth2Exception) e; return ResponseEntity .status(200 ) .body(new CustomOauthException (oAuth2Exception.getMessage())); } }
ResourceServerConfig 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 package com.cactus.auth2.config;import org.springframework.beans.factory.annotation.Autowired;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;import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;@Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure (HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/decision/**" ,"/govern/**" ).hasAnyRole("USER" ,"ADMIN" ) .antMatchers("/admin/**" ).hasRole("ADMIN" ) .antMatchers("/test/**" ).authenticated() .anyRequest().permitAll() .and().anonymous(); } }
WebSecurityConfig 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 package com.cactus.auth2.config;import com.cactus.auth2.service.UserAuthService;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.method.configuration.EnableGlobalMethodSecurity;import org.springframework.security.config.annotation.web.builders.HttpSecurity;import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import org.springframework.security.crypto.password.PasswordEncoder;@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Bean public PasswordEncoder passwordEncoder () { return new BCryptPasswordEncoder (); } @Bean public AuthenticationManager authenticationManagerBean () throws Exception { return super .authenticationManagerBean() ; } @Override protected void configure (AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder()); } @Override protected void configure (HttpSecurity http) throws Exception { http.csrf().disable(); http.requestMatchers() .antMatchers("/oauth/**" , "/login/**" , "/logout/**" ) .and() .authorizeRequests() .antMatchers("/oauth/**" ).authenticated() .and() .formLogin(); } }
TestController 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.cactus.auth2.controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController public class TestController { @RequestMapping("/test") public String test () { return "test" ; } }
Application 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.cactus.auth2;import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;@SpringBootApplication @MapperScan(basePackages = "com.cactus.auth2.mapper") public class Application { public static void main (String[] args) { SpringApplication.run(Application.class, args); BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder (); String password = passwordEncoder.encode("admin" ); System.out.println(password); } }
9.测试 此处在oauth_client_details.sql配置了两个客户端,以及登录方式
9.1账号密码登录 1 2 3 4 5 6 7 8 9 10 11 12 POST http://localhost:8001/oauth/token?username=cqc& password=admin& grant_ type=password& client_ id=client& client_ secret=123456& grant_ type=refresh_ token { "access_ token": "fFJqdNi5bKN9bbnC67nHrYP4B54", "token_ type": "bearer", "refresh_ token": "3Lzb46zVp3rBFfndNTABLm080zg", "expires_ in": 7199, "scope": "read write" }
验证
9.2客户端登录 1 2 3 4 5 6 7 8 POST http://localhost:8001/oauth/token?grant_ type=client_ credentials& client_ id=client_ 1& client_ secret=123456 { "access_ token": "1EFpbWyx0yYLBFd02LPxiATr2XE", "token_ type": "bearer", "expires_ in": 6931, "scope": "read write" }
测试