OAuth2获取授权令牌(token)通常有四种方式:授权码模式,简化模式,客户端模式,和密码模式。针对自己系统内用户的登录,通常使用密码模式进行授权。
我们利用Spring Security OAuth2来制作一个授权服务器。
pom文件中添加如下依赖,引入oauth2相关框架
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-webartifactId>
- dependency>
- <dependency>
- <groupId>org.springframework.cloudgroupId>
- <artifactId>spring-cloud-starter-securityartifactId>
- dependency>
- <dependency>
- <groupId>org.springframework.cloudgroupId>
- <artifactId>spring-cloud-starter-oauth2artifactId>
- dependency>
我还是用到了数据库进行存储,我用的jpa连接数据库,使用其他持久层框架(MyBatis)也可以。
引入数据库依赖
- <dependency>
- <groupId>org.springframework.bootgroupId>
- <artifactId>spring-boot-starter-data-jpaartifactId>
- dependency>
-
- <dependency>
- <groupId>mysqlgroupId>
- <artifactId>mysql-connector-javaartifactId>
- dependency>
- @Service
- public class MyUserDetailsService implements UserDetailsService {
-
- @Resource
- private UserService userService;
-
- @Override
- public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
- //根据用户名获取用户,并验证用户是否有效及权限
- //从数据库中获取用户
- TUser user = userService.findByUsername(username);
- if (user == null) {
- throw new UsernameNotFoundException("用户不存在");
- }
- Set
grantedAuthorities = new HashSet<>(); - boolean enabled = user.getStatus() == 1; // 可用性 :true:可用 false:不可用
- boolean accountNonExpired = true; // 过期性 :true:没过期 false:过期
- boolean credentialsNonExpired = true; // 有效性 :true:凭证有效 false:凭证无效
- boolean accountNonLocked = true; // 锁定性 :true:未锁定 false:已锁定
- //配置权限
- GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ADMIN");
- grantedAuthorities.add(grantedAuthority);
-
- //将用户名和密码及其他配置返还个spring security 进行验证
- return new User(username, user.getPassword(),
- enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, grantedAuthorities);
- }
-
- }
- @Configuration
- @EnableWebSecurity
- public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
-
- @Bean
- public PasswordEncoder passwordEncoder() {
- return new BCryptPasswordEncoder();
- }
-
- @Override
- @Bean
- public AuthenticationManager authenticationManagerBean() throws Exception {
- return super.authenticationManagerBean();
- }
-
-
- }
- @Configuration
- @EnableAuthorizationServer
- public class Oauth2ServerConfig extends AuthorizationServerConfigurerAdapter {
-
- //验证管理器
- @Resource
- private AuthenticationManager authenticationManager;
-
- //获取用户,自己实现获取用户的相关功能
- @Resource
- private MyUserDetailsService userService;
-
- //数据库配置
- @Resource
- private DataSource dataSource;
-
- /**
- * 自定义授权服务配置
- */
- @Override
- public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
- endpoints.authenticationManager(authenticationManager)
- .userDetailsService(userService)
- .tokenStore(new JdbcTokenStore(dataSource));
-
- // 配置TokenServices参数
- DefaultTokenServices tokenServices = new DefaultTokenServices();
- tokenServices.setTokenStore(endpoints.getTokenStore());
- tokenServices.setSupportRefreshToken(true);
- tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
- tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
- tokenServices.setAccessTokenValiditySeconds((int) TimeUnit.HOURS.toSeconds(12)); // 12小时
- tokenServices.setRefreshTokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(30));// 30天
- endpoints.tokenServices(tokenServices);
- }
-
- /**
- * 配置认证客户端
- * @param clients
- * @throws Exception
- */
- @Override
- public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
- //自定义客户端配置
- clients.withClientDetails(clientDetails());
- }
-
- //从数据库中获取客户端的配置
- public ClientDetailsService clientDetails() {
- return new JdbcClientDetailsService(dataSource);
- }
-
- /**
- * 自定义授权令牌端点的安全约束
- * @param security
- */
- @Override
- public void configure(AuthorizationServerSecurityConfigurer security) {
- //自定义安全约束
- security.allowFormAuthenticationForClients();
- }
-
- }
在数据库中创建三个表 oauth_access_token (存储token),oauth_client_details(允许请求授权的客户端),oauth_refresh_token(存储refreshToken)
为了测试,我还建了一个t_user的用户表,这个表可以不导入
- 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;
-
-
- 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$My8G.sWJs/WQN8hdYS862.BsUuoL4p51xyfTIJu2NMMrIQ/JXRc2a', 'web', 'authorization_code,password,refresh_token,client_credentials', NULL, NULL, NULL, NULL, '{\"code\":\"test\"}', NULL);
-
- 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;
-
-
- -- 我自己测试用的用户表,这个可以不导入,使用自己系统的用户表
- DROP TABLE IF EXISTS `t_user`;
- CREATE TABLE `t_user` (
- `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
- `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
- `nickname` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '昵称',
- `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
- `status` int(11) NULL DEFAULT NULL COMMENT '状态 1正常 2停用',
- `e_mail` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '电子邮箱',
- `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号',
- PRIMARY KEY (`id`) USING BTREE
- ) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-
- INSERT INTO `t_user` VALUES (1, 'admin', '管理员', '$2a$10$gD1u5uXEmCFmlvg.hgN7P.zv.sbCOEmX1sFNRHEBRIx6Ad.qydceu', 1, 'admin@admin.com', '15812345678');
-
在application中配置数据库信息
- spring:
- application:
- name: HelloSecurity
- #数据库配置连接
- datasource:
- url: jdbc:mysql://127.0.0.1:3306/hello_security?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
- username: root
- password: "123456"
- driver-class-name: com.mysql.cj.jdbc.Driver
- jpa:
- show-sql: true
-
- server:
- port: 8080
完成以上步骤后,一个简单的OAuth2授权验证服务器就搭建完成了,我们启动项目,进行测试。
获取token的接口是 http://127.0.0.1:8080/oauth/token
