fix bugs
This commit is contained in:
54
blade-core-oauth2/pom.xml
Normal file
54
blade-core-oauth2/pom.xml
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>
|
||||
<parent>
|
||||
<artifactId>BladeX-Tool</artifactId>
|
||||
<groupId>org.springblade</groupId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>blade-core-oauth2</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
<version>${project.parent.version}</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<!--Blade-->
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-secure</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-starter-social</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-starter-redis</artifactId>
|
||||
</dependency>
|
||||
<!-- captcha -->
|
||||
<dependency>
|
||||
<groupId>com.github.whvcse</groupId>
|
||||
<artifactId>easy-captcha</artifactId>
|
||||
</dependency>
|
||||
<!-- session -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.session</groupId>
|
||||
<artifactId>spring-session-data-redis</artifactId>
|
||||
</dependency>
|
||||
<!-- thymeleaf -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
<!-- Auto -->
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-auto</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.config;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springblade.core.jwt.props.JwtProperties;
|
||||
import org.springblade.core.oauth2.granter.TokenGranter;
|
||||
import org.springblade.core.oauth2.granter.TokenGranterEnhancer;
|
||||
import org.springblade.core.oauth2.granter.TokenGranterFactory;
|
||||
import org.springblade.core.oauth2.handler.*;
|
||||
import org.springblade.core.oauth2.props.OAuth2Properties;
|
||||
import org.springblade.core.oauth2.service.OAuth2ClientService;
|
||||
import org.springblade.core.oauth2.service.OAuth2UserService;
|
||||
import org.springblade.core.oauth2.service.impl.OAuth2ClientDetailService;
|
||||
import org.springblade.core.oauth2.service.impl.OAuth2UserDetailService;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* OAuth2Configuration
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@EnableConfigurationProperties(OAuth2Properties.class)
|
||||
@ConditionalOnProperty(value = OAuth2Properties.PREFIX + ".enabled", havingValue = "true", matchIfMissing = true)
|
||||
public class OAuth2AutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public AuthorizationHandler authorizationHandler() {
|
||||
return new OAuth2AuthorizationHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public PasswordHandler passwordHandler() {
|
||||
return new OAuth2PasswordHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public TokenHandler tokenHandler(JwtProperties properties) {
|
||||
return new OAuth2TokenHandler(properties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public OAuth2ClientService oAuth2ClientService(JdbcTemplate jdbcTemplate) {
|
||||
return new OAuth2ClientDetailService(jdbcTemplate);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public OAuth2UserService oAuth2UserService(JdbcTemplate jdbcTemplate) {
|
||||
return new OAuth2UserDetailService(jdbcTemplate);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TokenGranterFactory tokenGranterFactory(List<TokenGranter> tokenGranters, List<TokenGranterEnhancer> tokenGranterEnhancers, OAuth2Properties properties) {
|
||||
return new TokenGranterFactory(tokenGranters, tokenGranterEnhancers, properties);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.config;
|
||||
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* OAuth资源配置
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@AutoConfiguration
|
||||
public class OAuth2WebConfiguration implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.constant;
|
||||
|
||||
/**
|
||||
* OAuth2AuthorizationConstant
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface OAuth2AuthorizationConstant {
|
||||
|
||||
/**
|
||||
* 用户session key
|
||||
*/
|
||||
String AUTHORIZATION_SESSION_KEY = "user";
|
||||
|
||||
/**
|
||||
* 授权请求key
|
||||
*/
|
||||
String AUTHORIZATION_REQUEST_KEY = "authorizationRequest";
|
||||
|
||||
/**
|
||||
* 跳转参数
|
||||
*/
|
||||
String REDIRECT_URL = "redirect:";
|
||||
|
||||
/**
|
||||
* 授权地址
|
||||
*/
|
||||
String AUTHORIZE_URL = "/oauth/authorize";
|
||||
|
||||
/**
|
||||
* 登录地址
|
||||
*/
|
||||
String LOGIN_URL = "/oauth/login";
|
||||
|
||||
/**
|
||||
* 错误地址
|
||||
*/
|
||||
String ERROR_URL = "/oauth/error";
|
||||
|
||||
/**
|
||||
* 授权视图
|
||||
*/
|
||||
String AUTHORIZE_MODEL = "authorize";
|
||||
|
||||
/**
|
||||
* 登录视图
|
||||
*/
|
||||
String LOGIN_MODEL = "login";
|
||||
|
||||
/**
|
||||
* 错误视图
|
||||
*/
|
||||
String ERROR_MODEL = "error";
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.constant;
|
||||
|
||||
/**
|
||||
* OAuth2ClientConstant
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface OAuth2ClientConstant {
|
||||
|
||||
/**
|
||||
* blade_client表字段
|
||||
*/
|
||||
String CLIENT_FIELDS = "id, client_id, client_secret, resource_ids, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove";
|
||||
|
||||
/**
|
||||
* blade_client查询语句
|
||||
*/
|
||||
String BASE_STATEMENT = "select " + CLIENT_FIELDS + " from blade_client";
|
||||
|
||||
/**
|
||||
* blade_client查询排序
|
||||
*/
|
||||
String DEFAULT_FIND_STATEMENT = BASE_STATEMENT + " order by client_id";
|
||||
|
||||
/**
|
||||
* 查询client_id
|
||||
*/
|
||||
String DEFAULT_SELECT_STATEMENT = BASE_STATEMENT + " where client_id = ?";
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.constant;
|
||||
|
||||
/**
|
||||
* GranterTypeConstant
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface OAuth2GranterConstant {
|
||||
|
||||
/**
|
||||
* 授权码模式
|
||||
*/
|
||||
String AUTHORIZATION_CODE = "authorization_code";
|
||||
/**
|
||||
* 密码模式
|
||||
*/
|
||||
String PASSWORD = "password";
|
||||
/**
|
||||
* 刷新token模式
|
||||
*/
|
||||
String REFRESH_TOKEN = "refresh_token";
|
||||
/**
|
||||
* 客户端模式
|
||||
*/
|
||||
String CLIENT_CREDENTIALS = "client_credentials";
|
||||
/**
|
||||
* 简化模式
|
||||
*/
|
||||
String IMPLICIT = "implicit";
|
||||
/**
|
||||
* 验证码模式
|
||||
*/
|
||||
String CAPTCHA = "captcha";
|
||||
/**
|
||||
* 手机验证码模式
|
||||
*/
|
||||
String SMS_CODE = "sms_code";
|
||||
/**
|
||||
* 微信小程序模式
|
||||
*/
|
||||
String WECHAT_APPLET = "wechat_applet";
|
||||
/**
|
||||
* 开放平台模式
|
||||
*/
|
||||
String SOCIAL = "social";
|
||||
/**
|
||||
* 注册模式
|
||||
*/
|
||||
String REGISTER = "register";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.constant;
|
||||
|
||||
/**
|
||||
* OAuth2常量.
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface OAuth2ParameterConstant {
|
||||
|
||||
/**
|
||||
* 客户端id
|
||||
*/
|
||||
String CLIENT_ID = "client_id";
|
||||
/**
|
||||
* 客户端密钥
|
||||
*/
|
||||
String CLIENT_SECRET = "client_secret";
|
||||
/**
|
||||
* 令牌
|
||||
*/
|
||||
String ACCESS_TOKEN = "access_token";
|
||||
/**
|
||||
* 刷新令牌
|
||||
*/
|
||||
String REFRESH_TOKEN = "refresh_token";
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
String TENANT_ID = "tenant_id";
|
||||
/**
|
||||
* 用户名字
|
||||
*/
|
||||
String NAME = "name";
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
String USERNAME = "username";
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
String PASSWORD = "password";
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
String PHONE = "phone";
|
||||
/**
|
||||
* 电子游戏
|
||||
*/
|
||||
String EMAIL = "email";
|
||||
/**
|
||||
* 授权类型
|
||||
*/
|
||||
String GRANT_TYPE = "grant_type";
|
||||
/**
|
||||
* 响应类型
|
||||
*/
|
||||
String SCOPE = "scope";
|
||||
/**
|
||||
* 重定向地址
|
||||
*/
|
||||
String REDIRECT_URI = "redirect_uri";
|
||||
/**
|
||||
* 返回类型
|
||||
*/
|
||||
String RESPONSE_TYPE = "response_type";
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
String STATE = "state";
|
||||
/**
|
||||
* 验证
|
||||
*/
|
||||
String CODE = "code";
|
||||
/**
|
||||
* 来源
|
||||
*/
|
||||
String SOURCE = "source";
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.constant;
|
||||
|
||||
/**
|
||||
* OAuth2ResponseConstant
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface OAuth2ResponseConstant {
|
||||
String SUCCESS = "success";
|
||||
String ERROR_CODE = "error_code";
|
||||
String ERROR_DESCRIPTION = "error_description";
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.constant;
|
||||
|
||||
/**
|
||||
* TokenConstant
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface OAuth2TokenConstant {
|
||||
|
||||
String HEADER_AUTHORIZATION = "Authorization";
|
||||
String HEADER_AUTHORIZATION_PREFIX = "Basic ";
|
||||
String TOKEN_HEADER = "Blade-Auth";
|
||||
String TENANT_HEADER = "Tenant-Id";
|
||||
String DEFAULT_TENANT_ID = "000000";
|
||||
String USER_HEADER = "User-Id";
|
||||
String DEPT_HEADER = "Dept-Id";
|
||||
String ROLE_HEADER = "Role-Id";
|
||||
String USER_TYPE_HEADER = "User-Type";
|
||||
String DEFAULT_USER_TYPE = "web";
|
||||
String USER_FAIL_KEY = "blade:user::blade:fail:";
|
||||
String CAPTCHA_CACHE_KEY = "blade:auth::blade:captcha:";
|
||||
String CAPTCHA_HEADER_KEY = "Captcha-Key";
|
||||
String CAPTCHA_HEADER_CODE = "Captcha-Code";
|
||||
String CAPTCHA_NOT_CORRECT = "验证码不正确";
|
||||
String TOKEN_NOT_PERMISSION = "令牌授权已过期";
|
||||
String USER_NOT_FOUND = "用户名或密码错误";
|
||||
String USER_HAS_NO_ROLE = "未获得用户的角色信息";
|
||||
String USER_HAS_NO_TENANT = "未获得用户的租户信息";
|
||||
String USER_HAS_NO_TENANT_PERMISSION = "租户授权已过期,请联系管理员";
|
||||
String USER_HAS_TOO_MANY_FAILS = "登录错误次数过多,请稍后再试";
|
||||
String DEFAULT_AVATAR = "https://bladex.cn/images/logo.png";
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.constant;
|
||||
|
||||
/**
|
||||
* OAuth2UserConstant
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface OAuth2UserConstant {
|
||||
|
||||
/**
|
||||
* blade_user查询
|
||||
*/
|
||||
String DEFAULT_USERID_SELECT_STATEMENT = "select id as user_id, tenant_id , account, password from blade_user where id = ?";
|
||||
|
||||
/**
|
||||
* blade_user查询
|
||||
*/
|
||||
String DEFAULT_USERNAME_SELECT_STATEMENT = "select id as user_id, tenant_id , account, password from blade_user where account = ?";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.endpoint;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springblade.core.oauth2.constant.OAuth2AuthorizationConstant;
|
||||
import org.springblade.core.oauth2.handler.PasswordHandler;
|
||||
import org.springblade.core.oauth2.provider.OAuth2AuthorizationRequest;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.service.OAuth2Client;
|
||||
import org.springblade.core.oauth2.service.OAuth2ClientService;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
import org.springblade.core.oauth2.service.OAuth2UserService;
|
||||
import org.springblade.core.oauth2.utils.OAuth2CodeUtil;
|
||||
import org.springblade.core.redis.cache.BladeRedis;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.SessionAttribute;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.springblade.core.oauth2.constant.OAuth2ParameterConstant.*;
|
||||
|
||||
/**
|
||||
* AuthorizationEndpoint
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Controller
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "用户授权码模式认证", description = "2 - OAuth2授权码模式端点")
|
||||
public class OAuth2AuthorizationEndpoint implements OAuth2AuthorizationConstant {
|
||||
|
||||
private final BladeRedis bladeRedis;
|
||||
|
||||
private final OAuth2ClientService clientService;
|
||||
|
||||
private final OAuth2UserService userService;
|
||||
|
||||
private final PasswordHandler passwordHandler;
|
||||
|
||||
@GetMapping("/oauth/login")
|
||||
public String loginPage(HttpSession session, Model model) {
|
||||
// 从session中获取授权请求参数
|
||||
Optional.ofNullable((OAuth2AuthorizationRequest) session.getAttribute(AUTHORIZATION_REQUEST_KEY))
|
||||
.ifPresent(authorizationRequest -> model.addAttribute(AUTHORIZATION_REQUEST_KEY, authorizationRequest));
|
||||
// 返回登录页面视图
|
||||
return LOGIN_MODEL;
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/oauth/login/perform")
|
||||
public String performLogin(@SessionAttribute(AUTHORIZATION_REQUEST_KEY) OAuth2AuthorizationRequest authorizationRequest,
|
||||
RedirectAttributes redirectAttributes, HttpSession session) {
|
||||
// 根据用户名和密码验证用户
|
||||
return Optional.ofNullable(authenticateUser(session, authorizationRequest))
|
||||
.map(user -> {
|
||||
// 用户验证成功,处理授权请求参数和重定向
|
||||
authorizationRequest.setTenantId(user.getTenantId());
|
||||
session.setAttribute(AUTHORIZATION_REQUEST_KEY, authorizationRequest);
|
||||
redirectAttributes.addAllAttributes(authorizationRequest.getParameters());
|
||||
return REDIRECT_URL + AUTHORIZE_URL; // 重定向回授权视图
|
||||
})
|
||||
.orElse(REDIRECT_URL + ERROR_URL); // 用户验证失败,重定向回失败视图
|
||||
}
|
||||
|
||||
@GetMapping("/oauth/authorize")
|
||||
public String authorize(@SessionAttribute(value = AUTHORIZATION_REQUEST_KEY, required = false) OAuth2AuthorizationRequest authorizationRequest,
|
||||
HttpSession session, Model model) {
|
||||
// 获取授权请求参数
|
||||
OAuth2AuthorizationRequest request = OAuth2AuthorizationRequest.create().buildParameters();
|
||||
|
||||
// 设置请求参数
|
||||
Optional.ofNullable(authorizationRequest).ifPresentOrElse(authReq -> {
|
||||
if (request.getState() == null) {
|
||||
request.setState(authReq.getState());
|
||||
}
|
||||
if (request.getClientId() != null) {
|
||||
session.setAttribute(AUTHORIZATION_REQUEST_KEY, request);
|
||||
}
|
||||
}, () -> session.setAttribute(AUTHORIZATION_REQUEST_KEY, request));
|
||||
|
||||
// 获取用户信息并跳转
|
||||
return Optional.ofNullable(session.getAttribute(AUTHORIZATION_SESSION_KEY))
|
||||
.map(obj -> (OAuth2User) obj)
|
||||
.map(user -> {
|
||||
model.addAttribute(USERNAME, user.getAccount());
|
||||
model.addAllAttributes(request.getParameters());
|
||||
return AUTHORIZE_MODEL; // 用户已登录,显示授权页面
|
||||
})
|
||||
.orElse(REDIRECT_URL + LOGIN_URL); // 用户未登录,重定向到登录页面
|
||||
}
|
||||
|
||||
@PostMapping("/oauth/authorize/perform")
|
||||
public String performAuthorize(@RequestParam Boolean approval,
|
||||
@RequestParam(required = false) String state,
|
||||
@SessionAttribute(AUTHORIZATION_REQUEST_KEY) OAuth2AuthorizationRequest authorizationRequest,
|
||||
RedirectAttributes redirectAttributes, HttpSession session) {
|
||||
// 此处可以添加用户同意授权的处理逻辑
|
||||
if (!approval) {
|
||||
// 用户拒绝授权,返回授权页面
|
||||
return REDIRECT_URL + LOGIN_URL;
|
||||
}
|
||||
|
||||
// 获取客户端信息
|
||||
OAuth2Client client = clientService.loadByClientId(authorizationRequest.getClientId());
|
||||
|
||||
// 校验回调地址信息
|
||||
if (!clientService.validateRedirectUri(client, authorizationRequest.getRedirectUri())) {
|
||||
// 重定向URI参数不匹配,返回错误页面
|
||||
return ERROR_MODEL;
|
||||
}
|
||||
|
||||
// 生成授权码
|
||||
String code = createCode();
|
||||
|
||||
// 设置用户信息
|
||||
OAuth2User user = (OAuth2User) session.getAttribute(AUTHORIZATION_SESSION_KEY);
|
||||
if (user == null) {
|
||||
// 用户未登录,重定向到登录页面
|
||||
return REDIRECT_URL + LOGIN_URL;
|
||||
}
|
||||
|
||||
// 校验state参数
|
||||
if (Func.equalsSafe(authorizationRequest.getState(), state)) {
|
||||
// 保存授权码
|
||||
saveCode(code, user);
|
||||
} else {
|
||||
// 重定向URI和state参数不匹配,返回错误页面
|
||||
return ERROR_MODEL;
|
||||
}
|
||||
|
||||
// 使用RedirectAttributes添加授权码和state参数
|
||||
redirectAttributes.addAttribute(CODE, code);
|
||||
|
||||
// 添加tenantId参数为state参数
|
||||
if (authorizationRequest.getTenantId() != null) {
|
||||
redirectAttributes.addAttribute(STATE, authorizationRequest.getTenantId());
|
||||
}
|
||||
// 用户自定义state参数则覆盖
|
||||
if (state != null) {
|
||||
redirectAttributes.addAttribute(STATE, state);
|
||||
}
|
||||
|
||||
// 重定向到客户端提供的重定向URI
|
||||
return REDIRECT_URL + authorizationRequest.getRedirectUri();
|
||||
}
|
||||
|
||||
@GetMapping("/oauth/authorize/logout")
|
||||
public String logout(HttpSession session) {
|
||||
// 退出登录,清除session中的用户信息
|
||||
session.removeAttribute(AUTHORIZATION_SESSION_KEY);
|
||||
return REDIRECT_URL + LOGIN_URL;
|
||||
}
|
||||
|
||||
@GetMapping("/oauth/error")
|
||||
public String error() {
|
||||
// 返回错误页面
|
||||
return ERROR_MODEL;
|
||||
}
|
||||
|
||||
private OAuth2User authenticateUser(HttpSession session, OAuth2AuthorizationRequest authorizationRequest) {
|
||||
// 创建 OAuth2 请求对象并构建参数
|
||||
OAuth2Request request = OAuth2Request.create().buildArgs();
|
||||
|
||||
// 获取请求参数
|
||||
String username = request.getUsername();
|
||||
String password = request.getPassword();
|
||||
String clientId = authorizationRequest.getClientId();
|
||||
String redirectUri = authorizationRequest.getRedirectUri();
|
||||
|
||||
// 获取客户端信息
|
||||
OAuth2Client client = clientService.loadByClientId(clientId);
|
||||
|
||||
// 校验回调地址信息
|
||||
if (!clientService.validateRedirectUri(client, redirectUri)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
OAuth2User user = userService.loadByUsername(username, request);
|
||||
|
||||
// 校验用户信息
|
||||
if (!userService.validateUser(user)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 校验用户密码
|
||||
if (!passwordHandler.matches(password, user.getPassword())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 将用户信息存入session
|
||||
session.setAttribute(AUTHORIZATION_SESSION_KEY, user);
|
||||
|
||||
// 返回用户信息
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权码模式获取授权码
|
||||
*
|
||||
* @return 授权码
|
||||
*/
|
||||
private String createCode() {
|
||||
// 生成6位随机数作为授权码
|
||||
String code = StringUtil.random(6);
|
||||
if (bladeRedis.exists(OAuth2CodeUtil.codeKey(code))) {
|
||||
// 如果生成的授权码已存在,则递归调用重新生成
|
||||
return createCode();
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存code信息
|
||||
*/
|
||||
private void saveCode(String code, OAuth2User user) {
|
||||
// 保存code信息到redis,30分钟过期
|
||||
bladeRedis.setEx(OAuth2CodeUtil.codeKey(code), user, Duration.ofMinutes(30));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据code获取用户信息
|
||||
*
|
||||
* @param code code
|
||||
* @return 用户信息
|
||||
*/
|
||||
public OAuth2User getUserByCode(String code) {
|
||||
// 根据code从redis中获取用户信息
|
||||
return bladeRedis.get(OAuth2CodeUtil.codeKey(code));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.endpoint;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhyd.oauth.model.AuthCallback;
|
||||
import me.zhyd.oauth.model.AuthToken;
|
||||
import me.zhyd.oauth.request.AuthRequest;
|
||||
import me.zhyd.oauth.utils.AuthStateUtils;
|
||||
import org.springblade.core.social.props.SocialProperties;
|
||||
import org.springblade.core.social.utils.SocialUtil;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 第三方登录端点
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@ConditionalOnProperty(value = "social.enabled", havingValue = "true")
|
||||
@Tag(name = "开放平台登录", description = "3 - 开放平台登录端点")
|
||||
public class OAuth2SocialEndpoint {
|
||||
|
||||
private final SocialProperties socialProperties;
|
||||
|
||||
/**
|
||||
* 授权完毕跳转
|
||||
*/
|
||||
@Operation(summary = "授权完毕跳转")
|
||||
@RequestMapping("/oauth/render/{source}")
|
||||
public void renderAuth(@PathVariable("source") String source, HttpServletResponse response) throws IOException {
|
||||
AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
|
||||
String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
|
||||
response.sendRedirect(authorizeUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取认证信息
|
||||
*/
|
||||
@Operation(summary = "获取认证信息")
|
||||
@RequestMapping("/oauth/callback/{source}")
|
||||
public Object login(@PathVariable("source") String source, AuthCallback callback) {
|
||||
AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
|
||||
return authRequest.login(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销授权
|
||||
*/
|
||||
@Operation(summary = "撤销授权")
|
||||
@RequestMapping("/oauth/revoke/{source}/{token}")
|
||||
public Object revokeAuth(@PathVariable("source") String source, @PathVariable("token") String token) {
|
||||
AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
|
||||
return authRequest.revoke(AuthToken.builder().accessToken(token).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 续期accessToken
|
||||
*/
|
||||
@Operation(summary = "续期令牌")
|
||||
@RequestMapping("/oauth/refresh/{source}")
|
||||
public Object refreshAuth(@PathVariable("source") String source, String token) {
|
||||
AuthRequest authRequest = SocialUtil.getAuthRequest(source, socialProperties);
|
||||
return authRequest.refresh(AuthToken.builder().refreshToken(token).build());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.endpoint;
|
||||
|
||||
import com.wf.captcha.SpecCaptcha;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.enums.ParameterIn;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springblade.core.cache.utils.CacheUtil;
|
||||
import org.springblade.core.jwt.JwtUtil;
|
||||
import org.springblade.core.jwt.props.JwtProperties;
|
||||
import org.springblade.core.oauth2.constant.OAuth2ParameterConstant;
|
||||
import org.springblade.core.oauth2.granter.TokenGranter;
|
||||
import org.springblade.core.oauth2.granter.TokenGranterFactory;
|
||||
import org.springblade.core.oauth2.handler.AuthorizationHandler;
|
||||
import org.springblade.core.oauth2.handler.TokenHandler;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Token;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Validation;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
import org.springblade.core.oauth2.utils.OAuth2ExceptionUtil;
|
||||
import org.springblade.core.redis.cache.BladeRedis;
|
||||
import org.springblade.core.secure.BladeUser;
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.core.tool.support.Kv;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.springblade.core.cache.constant.CacheConstant.*;
|
||||
import static org.springblade.core.oauth2.constant.OAuth2TokenConstant.CAPTCHA_CACHE_KEY;
|
||||
|
||||
/**
|
||||
* OAuth2认证端点
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@Tag(name = "用户授权认证", description = "1 - OAuth2授权认证端点")
|
||||
public class OAuth2TokenEndPoint {
|
||||
|
||||
private final BladeRedis bladeRedis;
|
||||
private final JwtProperties jwtProperties;
|
||||
|
||||
private final TokenGranterFactory granterFactory;
|
||||
private final AuthorizationHandler authorizationHandler;
|
||||
private final TokenHandler tokenHandler;
|
||||
|
||||
|
||||
@PostMapping("/oauth/token")
|
||||
@Operation(
|
||||
summary = "获取Token",
|
||||
description = "OAuth2认证接口",
|
||||
parameters = {
|
||||
@Parameter(in = ParameterIn.QUERY, name = OAuth2ParameterConstant.USERNAME, description = "账号", schema = @Schema(type = "string")),
|
||||
@Parameter(in = ParameterIn.QUERY, name = OAuth2ParameterConstant.PASSWORD, description = "密码", schema = @Schema(type = "string")),
|
||||
@Parameter(in = ParameterIn.QUERY, name = OAuth2ParameterConstant.GRANT_TYPE, description = "授权类型", schema = @Schema(type = "string")),
|
||||
@Parameter(in = ParameterIn.QUERY, name = OAuth2ParameterConstant.REFRESH_TOKEN, description = "刷新token", schema = @Schema(type = "string")),
|
||||
@Parameter(in = ParameterIn.QUERY, name = OAuth2ParameterConstant.SCOPE, description = "权限范围", schema = @Schema(type = "string"))
|
||||
}
|
||||
)
|
||||
public ResponseEntity<?> token() {
|
||||
// 创建 OAuth2 请求对象并构建参数
|
||||
OAuth2Request request = OAuth2Request.create().buildArgs();
|
||||
|
||||
// 根据请求的授权类型创建对应的 TokenGranter
|
||||
TokenGranter tokenGranter = granterFactory.create(request.getGrantType());
|
||||
|
||||
// 使用 TokenGranter 获取用户信息
|
||||
OAuth2User user = tokenGranter.user(request);
|
||||
|
||||
// 使用授权处理器对用户进行验证
|
||||
OAuth2Validation validation = authorizationHandler.authValidation(user, request);
|
||||
|
||||
// 检查验证是否成功
|
||||
if (!validation.isSuccess()) {
|
||||
// 验证失败处理逻辑
|
||||
authorizationHandler.authFailure(user, request, validation);
|
||||
|
||||
// 根据验证失败的错误代码抛出异常
|
||||
OAuth2ExceptionUtil.throwFromCode(validation.getCode());
|
||||
}
|
||||
|
||||
// 创建令牌
|
||||
OAuth2Token token = tokenGranter.token(user, request);
|
||||
|
||||
// 对令牌进行增强处理
|
||||
OAuth2Token enhanceToken = tokenHandler.enhance(user, token, request);
|
||||
|
||||
// 验证成功处理逻辑
|
||||
authorizationHandler.authSuccessful(user, request);
|
||||
|
||||
// 返回增强后的令牌
|
||||
return ResponseEntity.ok(enhanceToken.getArgs());
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/oauth/logout")
|
||||
@Operation(summary = "退出登录")
|
||||
public Kv logout() {
|
||||
BladeUser user = AuthUtil.getUser();
|
||||
if (user != null && jwtProperties.getState()) {
|
||||
OAuth2Request request = OAuth2Request.create().buildHeaderArgs();
|
||||
String token = JwtUtil.getToken(request.getToken());
|
||||
JwtUtil.removeAccessToken(user.getTenantId(), user.getClientId(), String.valueOf(user.getUserId()), token);
|
||||
}
|
||||
return Kv.create().set("success", "true").set("msg", "success");
|
||||
}
|
||||
|
||||
@GetMapping("/oauth/captcha")
|
||||
@Operation(summary = "获取验证码")
|
||||
public Kv captcha() {
|
||||
SpecCaptcha specCaptcha = new SpecCaptcha(130, 48, 5);
|
||||
String verCode = specCaptcha.text().toLowerCase();
|
||||
String key = UUID.randomUUID().toString();
|
||||
// 存入redis并设置过期时间为30分钟
|
||||
bladeRedis.setEx(CAPTCHA_CACHE_KEY + key, verCode, Duration.ofMinutes(30));
|
||||
// 将key和base64返回给前端
|
||||
return Kv.create().set("key", key).set("image", specCaptcha.toBase64());
|
||||
}
|
||||
|
||||
@GetMapping("/oauth/clear-cache")
|
||||
@Operation(summary = "清除缓存")
|
||||
public Kv clearCache() {
|
||||
CacheUtil.clear(BIZ_CACHE);
|
||||
CacheUtil.clear(USER_CACHE);
|
||||
CacheUtil.clear(DICT_CACHE);
|
||||
CacheUtil.clear(FLOW_CACHE);
|
||||
CacheUtil.clear(SYS_CACHE);
|
||||
CacheUtil.clear(PARAM_CACHE);
|
||||
CacheUtil.clear(RESOURCE_CACHE);
|
||||
CacheUtil.clear(MENU_CACHE);
|
||||
CacheUtil.clear(DICT_CACHE, Boolean.FALSE);
|
||||
CacheUtil.clear(MENU_CACHE, Boolean.FALSE);
|
||||
CacheUtil.clear(SYS_CACHE, Boolean.FALSE);
|
||||
CacheUtil.clear(PARAM_CACHE, Boolean.FALSE);
|
||||
return Kv.create().set("success", "true").set("msg", "success");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.exception;
|
||||
|
||||
/**
|
||||
* 客户端认证失败
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public class ClientInvalidException extends OAuth2Exception {
|
||||
|
||||
public ClientInvalidException(String msg) {
|
||||
super(ExceptionCode.INVALID_CLIENT, msg);
|
||||
}
|
||||
|
||||
public ClientInvalidException(String msg, Throwable cause) {
|
||||
super(ExceptionCode.INVALID_CLIENT, msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.exception;
|
||||
|
||||
/**
|
||||
* 客户端未找到
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public class ClientNotFoundException extends OAuth2Exception {
|
||||
|
||||
public ClientNotFoundException(String msg) {
|
||||
super(ExceptionCode.CLIENT_NOT_FOUND, msg);
|
||||
}
|
||||
|
||||
public ClientNotFoundException(String msg, Throwable cause) {
|
||||
super(ExceptionCode.CLIENT_NOT_FOUND, msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.exception;
|
||||
|
||||
/**
|
||||
* 客户端未授权
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public class ClientUnauthorizedException extends OAuth2Exception {
|
||||
|
||||
public ClientUnauthorizedException(String msg) {
|
||||
super(ExceptionCode.UNAUTHORIZED_CLIENT, msg);
|
||||
}
|
||||
|
||||
public ClientUnauthorizedException(String msg, Throwable cause) {
|
||||
super(ExceptionCode.UNAUTHORIZED_CLIENT, msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.exception;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import static org.springblade.core.oauth2.exception.OAuth2ErrorMessage.INVALID_ERROR_CODE;
|
||||
|
||||
/**
|
||||
* OAuth2ExceptionCode
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ExceptionCode {
|
||||
|
||||
/**
|
||||
* 无效请求 - 请求缺少必要的参数或格式不正确。
|
||||
*/
|
||||
INVALID_REQUEST(OAuth2ErrorCode.INVALID_REQUEST, "无效请求"),
|
||||
|
||||
/**
|
||||
* 用户不存在 - 指定的用户ID不存在或无效。
|
||||
*/
|
||||
USER_NOT_FOUND(OAuth2ErrorCode.USER_NOT_FOUND, "用户不存在"),
|
||||
|
||||
/**
|
||||
* 用户租户不存在 - 指定的用户租户未授权。
|
||||
*/
|
||||
USER_TENANT_NOT_FOUND(OAuth2ErrorCode.USER_TENANT_NOT_FOUND, "用户租户不存在"),
|
||||
|
||||
/**
|
||||
* 用户登录失败次数过多 - 用户登录失败次数过多。
|
||||
*/
|
||||
USER_TOO_MANY_FAILS(OAuth2ErrorCode.USER_TOO_MANY_FAILS, "用户登录失败次数过多"),
|
||||
|
||||
/**
|
||||
* 用户认证失败 - 指定的用户认证信息错误或无效。
|
||||
*/
|
||||
INVALID_USER(OAuth2ErrorCode.INVALID_USER, "认证信息错误或无效"),
|
||||
|
||||
/**
|
||||
* 用户未授权 - 指定的用户未授权。
|
||||
*/
|
||||
UNAUTHORIZED_USER(OAuth2ErrorCode.UNAUTHORIZED_USER, "认证信息错误或无效"),
|
||||
|
||||
/**
|
||||
* 用户租户未授权 - 指定的用户租户未授权。
|
||||
*/
|
||||
UNAUTHORIZED_USER_TENANT(OAuth2ErrorCode.UNAUTHORIZED_USER_TENANT, "用户租户未授权"),
|
||||
|
||||
/**
|
||||
* 用户未授权 - 指定的用户未授权。
|
||||
*/
|
||||
INVALID_REFRESH_TOKEN(OAuth2ErrorCode.INVALID_REFRESH_TOKEN, "令牌刷新错误或无效"),
|
||||
|
||||
/**
|
||||
* 客户端不存在 - 指定的客户端ID不存在或无效。
|
||||
*/
|
||||
CLIENT_NOT_FOUND(OAuth2ErrorCode.CLIENT_NOT_FOUND, "客户端不存在"),
|
||||
|
||||
/**
|
||||
* 客户端认证失败 - 客户端提供的认证信息错误或无效。
|
||||
*/
|
||||
INVALID_CLIENT(OAuth2ErrorCode.INVALID_CLIENT, "客户端认证失败"),
|
||||
|
||||
/**
|
||||
* 回调地址错误或无效 - 客户端回调地址错误或无效。
|
||||
*/
|
||||
INVALID_CLIENT_REDIRECT_URI(OAuth2ErrorCode.INVALID_CLIENT_REDIRECT_URI, "客户端未授权"),
|
||||
|
||||
/**
|
||||
* 客户端未授权 - 客户端无权执行此操作。
|
||||
*/
|
||||
UNAUTHORIZED_CLIENT(OAuth2ErrorCode.UNAUTHORIZED_CLIENT, "客户端未授权"),
|
||||
|
||||
/**
|
||||
* 不支持的授权类型 - 请求的授权类型不被服务器支持。
|
||||
*/
|
||||
UNSUPPORTED_GRANT_TYPE(OAuth2ErrorCode.UNSUPPORTED_GRANT_TYPE, "不支持的授权类型"),
|
||||
|
||||
/**
|
||||
* 无效的授权类型 - 提供的授权令牌无效、过期或被撤销。
|
||||
*/
|
||||
INVALID_GRANTER(OAuth2ErrorCode.INVALID_GRANTER, "无效的授权类型"),
|
||||
|
||||
/**
|
||||
* 无效的无效的授权范围 - 请求的无效的授权范围无效、未知或格式不正确。
|
||||
*/
|
||||
INVALID_SCOPE(OAuth2ErrorCode.INVALID_SCOPE, "授权范围"),
|
||||
|
||||
/**
|
||||
* 服务器错误 - 服务器内部错误,无法完成请求。
|
||||
*/
|
||||
SERVER_ERROR(OAuth2ErrorCode.SERVER_ERROR, "服务器错误"),
|
||||
|
||||
/**
|
||||
* 访问被拒绝 - 由于各种原因,服务器拒绝执行此操作。
|
||||
*/
|
||||
ACCESS_DENIED(OAuth2ErrorCode.ACCESS_DENIED, "访问被拒绝"),
|
||||
|
||||
/**
|
||||
* 服务暂不可用 - 服务器暂时过载或维护,无法处理请求。
|
||||
*/
|
||||
TEMPORARILY_UNAVAILABLE(OAuth2ErrorCode.TEMPORARILY_UNAVAILABLE, "服务暂不可用");
|
||||
|
||||
final int code;
|
||||
final String message;
|
||||
|
||||
/**
|
||||
* 通过错误代码获取枚举
|
||||
*
|
||||
* @param code 错误代码
|
||||
* @return ExceptionCodeEnum
|
||||
*/
|
||||
public static ExceptionCode of(int code) {
|
||||
for (ExceptionCode value : ExceptionCode.values()) {
|
||||
if (value.code == code) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException(String.format(INVALID_ERROR_CODE, code));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.exception;
|
||||
|
||||
/**
|
||||
* 无效的授权
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public class GranterInvalidException extends OAuth2Exception {
|
||||
|
||||
public GranterInvalidException(String msg) {
|
||||
super(ExceptionCode.INVALID_GRANTER, msg);
|
||||
}
|
||||
|
||||
public GranterInvalidException(String msg, Throwable cause) {
|
||||
super(ExceptionCode.INVALID_GRANTER, msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.exception;
|
||||
|
||||
/**
|
||||
* OAuth2ErrorCodes
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface OAuth2ErrorCode {
|
||||
/**
|
||||
* 无效请求 - 请求缺少必要的参数或格式不正确。
|
||||
*/
|
||||
int INVALID_REQUEST = 2000;
|
||||
/**
|
||||
* 用户不存在 - 指定的用户ID不存在或无效。
|
||||
*/
|
||||
int USER_NOT_FOUND = 2001;
|
||||
/**
|
||||
* 用户租户不存在 - 指定的用户租户未授权。
|
||||
*/
|
||||
int USER_TENANT_NOT_FOUND = 2002;
|
||||
/**
|
||||
* 用户登录失败次数过多 - 用户登录失败次数过多。
|
||||
*/
|
||||
int USER_TOO_MANY_FAILS = 2003;
|
||||
/**
|
||||
* 用户认证失败 - 指定的用户认证信息错误或无效。
|
||||
*/
|
||||
int INVALID_USER = 2004;
|
||||
/**
|
||||
* 用户未授权 - 指定的用户未授权。
|
||||
*/
|
||||
int UNAUTHORIZED_USER = 2005;
|
||||
/**
|
||||
* 用户租户未授权 - 指定的用户租户未授权。
|
||||
*/
|
||||
int UNAUTHORIZED_USER_TENANT = 2006;
|
||||
/**
|
||||
* 令牌刷新错误或无效 - 刷新令牌认证信息错误或无效。
|
||||
*/
|
||||
int INVALID_REFRESH_TOKEN = 2010;
|
||||
/**
|
||||
* 客户端不存在 - 指定的客户端ID不存在或无效。
|
||||
*/
|
||||
int CLIENT_NOT_FOUND = 3000;
|
||||
/**
|
||||
* 客户端认证失败 - 客户端提供的认证信息错误或无效。
|
||||
*/
|
||||
int INVALID_CLIENT = 3001;
|
||||
/**
|
||||
* 回调地址错误或无效 - 客户端回调地址错误或无效。
|
||||
*/
|
||||
int INVALID_CLIENT_REDIRECT_URI = 3002;
|
||||
/**
|
||||
* 客户端未授权 - 客户端无权执行此操作。
|
||||
*/
|
||||
int UNAUTHORIZED_CLIENT = 3003;
|
||||
/**
|
||||
* 不支持的授权类型 - 请求的授权类型不被服务器支持。
|
||||
*/
|
||||
int UNSUPPORTED_GRANT_TYPE = 4000;
|
||||
/**
|
||||
* 无效的授权类型 - 提供的授权类型无效、过期或被撤销。
|
||||
*/
|
||||
int INVALID_GRANTER = 4001;
|
||||
/**
|
||||
* 无效的授权范围 - 请求的授权范围无效、未知或格式不正确。
|
||||
*/
|
||||
int INVALID_SCOPE = 4002;
|
||||
/**
|
||||
* 服务器错误 - 服务器内部错误,无法完成请求。
|
||||
*/
|
||||
int SERVER_ERROR = 5000;
|
||||
/**
|
||||
* 访问被拒绝 - 由于各种原因,服务器拒绝执行此操作。
|
||||
*/
|
||||
int ACCESS_DENIED = 5001;
|
||||
/**
|
||||
* 服务暂不可用 - 服务器暂时过载或维护,无法处理请求。
|
||||
*/
|
||||
int TEMPORARILY_UNAVAILABLE = 5002;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.exception;
|
||||
|
||||
/**
|
||||
* OAuth2ErrorMessage
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface OAuth2ErrorMessage {
|
||||
String INVALID_GRANT_TYPE = "无效的授权类型: %s";
|
||||
|
||||
String CLIENT_AUTHORIZATION_FAILED = "客户端认证失败, 请检查请求头 [Authorization] 信息";
|
||||
|
||||
String CLIENT_TOKEN_PARSE_FAILED = "客户端令牌解析失败";
|
||||
|
||||
String INVALID_CLIENT_TOKEN = "客户端令牌不合法";
|
||||
|
||||
String AUTHORIZATION_NOT_FOUND = "请求头中未找到 [Authorization] 信息";
|
||||
String INVALID_ERROR_CODE = "无效的错误代码: %s";
|
||||
String USER_HAS_NO_TENANT = "未获得用户的租户信息";
|
||||
String USER_HAS_NO_TENANT_PERMISSION = "租户授权已过期,请联系管理员";
|
||||
String USER_HAS_TOO_MANY_FAILS = "登录错误次数过多,请稍后再试";
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.exception;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* OAuth2通用异常
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Getter
|
||||
public class OAuth2Exception extends RuntimeException {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final ExceptionCode exceptionCode;
|
||||
|
||||
public OAuth2Exception(String message) {
|
||||
super(message);
|
||||
this.exceptionCode = ExceptionCode.ACCESS_DENIED;
|
||||
}
|
||||
|
||||
public OAuth2Exception(ExceptionCode exceptionCode) {
|
||||
super(exceptionCode.getMessage());
|
||||
this.exceptionCode = exceptionCode;
|
||||
}
|
||||
|
||||
public OAuth2Exception(ExceptionCode exceptionCode, String message) {
|
||||
super(message);
|
||||
this.exceptionCode = exceptionCode;
|
||||
}
|
||||
|
||||
public OAuth2Exception(ExceptionCode exceptionCode, Throwable cause) {
|
||||
super(cause);
|
||||
this.exceptionCode = exceptionCode;
|
||||
}
|
||||
|
||||
public OAuth2Exception(ExceptionCode exceptionCode, String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.exceptionCode = exceptionCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Throwable fillInStackTrace() {
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.exception;
|
||||
|
||||
import io.jsonwebtoken.JwtException;
|
||||
import org.springblade.core.oauth2.endpoint.OAuth2AuthorizationEndpoint;
|
||||
import org.springblade.core.oauth2.endpoint.OAuth2SocialEndpoint;
|
||||
import org.springblade.core.oauth2.endpoint.OAuth2TokenEndPoint;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Response;
|
||||
import org.springblade.core.secure.exception.SecureException;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
|
||||
/**
|
||||
* OAuth2ExceptionHandler
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@ControllerAdvice(basePackageClasses = {OAuth2AuthorizationEndpoint.class, OAuth2SocialEndpoint.class, OAuth2TokenEndPoint.class})
|
||||
public class OAuth2ExceptionHandler {
|
||||
@ExceptionHandler(OAuth2Exception.class)
|
||||
public ResponseEntity<?> handleOAuth2Exception(OAuth2Exception ex) {
|
||||
// 统一处理验证失败的情况
|
||||
return ResponseEntity.ok(OAuth2Response.create().of(Boolean.FALSE, ex.getExceptionCode().getCode(), ex.getMessage()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(SecureException.class)
|
||||
public ResponseEntity<?> handleSecureException(SecureException ex) {
|
||||
// 统一处理验证失败的情况
|
||||
return ResponseEntity.ok(OAuth2Response.create().of(Boolean.FALSE, OAuth2ErrorCode.INVALID_USER, ex.getMessage()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(JwtException.class)
|
||||
public ResponseEntity<?> handleJwtException(JwtException ex) {
|
||||
// 统一处理验证失败的情况
|
||||
return ResponseEntity.ok(OAuth2Response.create().of(Boolean.FALSE, OAuth2ErrorCode.ACCESS_DENIED, ex.getMessage()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.exception;
|
||||
|
||||
/**
|
||||
* 用户认证失败
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public class UserInvalidException extends OAuth2Exception {
|
||||
|
||||
public UserInvalidException(String msg) {
|
||||
super(ExceptionCode.INVALID_USER, msg);
|
||||
}
|
||||
|
||||
public UserInvalidException(String msg, Throwable cause) {
|
||||
super(ExceptionCode.INVALID_USER, msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.exception;
|
||||
|
||||
/**
|
||||
* 用户未授权
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public class UserUnauthorizedException extends OAuth2Exception {
|
||||
|
||||
public UserUnauthorizedException(String msg) {
|
||||
super(ExceptionCode.UNAUTHORIZED_USER, msg);
|
||||
}
|
||||
|
||||
public UserUnauthorizedException(String msg, Throwable cause) {
|
||||
super(ExceptionCode.UNAUTHORIZED_USER, msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.exception;
|
||||
|
||||
/**
|
||||
* 用户名未找到
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public class UsernameNotFoundException extends OAuth2Exception {
|
||||
|
||||
public UsernameNotFoundException(String msg) {
|
||||
super(ExceptionCode.USER_NOT_FOUND, msg);
|
||||
}
|
||||
|
||||
public UsernameNotFoundException(String msg, Throwable cause) {
|
||||
super(ExceptionCode.USER_NOT_FOUND, msg, cause);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.granter;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springblade.core.launch.constant.TokenConstant;
|
||||
import org.springblade.core.oauth2.exception.OAuth2ErrorCode;
|
||||
import org.springblade.core.oauth2.handler.PasswordHandler;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Token;
|
||||
import org.springblade.core.oauth2.service.OAuth2Client;
|
||||
import org.springblade.core.oauth2.service.OAuth2ClientService;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
import org.springblade.core.oauth2.service.OAuth2UserService;
|
||||
import org.springblade.core.oauth2.utils.OAuth2ExceptionUtil;
|
||||
import org.springblade.core.oauth2.utils.OAuth2Util;
|
||||
import org.springblade.core.secure.TokenInfo;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
|
||||
/**
|
||||
* AbstractTokenGranter
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public abstract class AbstractTokenGranter implements TokenGranter {
|
||||
|
||||
private final OAuth2ClientService clientService;
|
||||
private final OAuth2UserService userService;
|
||||
private final PasswordHandler passwordHandler;
|
||||
|
||||
protected TokenGranterEnhancer enhancer;
|
||||
|
||||
public abstract String type();
|
||||
|
||||
@Override
|
||||
public void enhancer(TokenGranterEnhancer enhancer) {
|
||||
this.enhancer = enhancer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2Client client(OAuth2Request request) {
|
||||
// 解析请求头
|
||||
String[] tokens = request.getClientFromAuthorization();
|
||||
// 获取clientId
|
||||
String clientId = tokens[0];
|
||||
// 获取clientSecret
|
||||
String clientSecret = tokens[1];
|
||||
|
||||
// 获取客户端信息
|
||||
OAuth2Client client = clientService.loadByClientId(clientId);
|
||||
|
||||
// 校验客户端信息
|
||||
if (!clientService.validateClient(client, clientId, clientSecret)) {
|
||||
OAuth2ExceptionUtil.throwFromCode(OAuth2ErrorCode.INVALID_CLIENT);
|
||||
}
|
||||
|
||||
// 校验授权类型
|
||||
if (!clientService.validateGranter(client, type())) {
|
||||
OAuth2ExceptionUtil.throwFromCode(OAuth2ErrorCode.INVALID_GRANTER);
|
||||
}
|
||||
|
||||
// 返回客户端信息
|
||||
return client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2User user(OAuth2Request request) {
|
||||
// 获取用户信息
|
||||
OAuth2User user = (StringUtil.isNotBlank(request.getUserId()) && request.isRefreshToken())
|
||||
? userService.loadByUserId(request.getUserId(), request)
|
||||
: userService.loadByUsername(request.getUsername(), request);
|
||||
|
||||
// 校验用户信息
|
||||
if (!userService.validateUser(user)) {
|
||||
OAuth2ExceptionUtil.throwFromCode(OAuth2ErrorCode.INVALID_USER);
|
||||
}
|
||||
|
||||
// 校验用户密码
|
||||
if ((request.isCaptchaCode() || request.isPassword()) && !passwordHandler.matches(request.getPassword(), user.getPassword())) {
|
||||
OAuth2ExceptionUtil.throwFromCode(OAuth2ErrorCode.INVALID_USER);
|
||||
}
|
||||
|
||||
// 设置客户端信息
|
||||
user.setClient(client(request));
|
||||
|
||||
// 返回用户信息
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2Token token(OAuth2User user, OAuth2Request request) {
|
||||
TokenInfo accessToken = OAuth2Util.createAccessToken(user);
|
||||
TokenInfo refreshToken = OAuth2Util.createRefreshToken(user);
|
||||
|
||||
OAuth2Token token = OAuth2Token.create();
|
||||
|
||||
token.getArgs().set(TokenConstant.TENANT_ID, user.getTenantId())
|
||||
.set(TokenConstant.USER_ID, user.getUserId())
|
||||
.set(TokenConstant.DEPT_ID, user.getDeptId())
|
||||
.set(TokenConstant.POST_ID, user.getPostId())
|
||||
.set(TokenConstant.ROLE_ID, user.getRoleId())
|
||||
.set(TokenConstant.OAUTH_ID, user.getOauthId())
|
||||
.set(TokenConstant.ACCOUNT, user.getAccount())
|
||||
.set(TokenConstant.USER_NAME, user.getAccount())
|
||||
.set(TokenConstant.NICK_NAME, user.getName())
|
||||
.set(TokenConstant.REAL_NAME, user.getRealName())
|
||||
.set(TokenConstant.ROLE_NAME, Func.join(user.getAuthorities()))
|
||||
.set(TokenConstant.AVATAR, Func.toStr(user.getAvatar(), TokenConstant.DEFAULT_AVATAR))
|
||||
.set(TokenConstant.ACCESS_TOKEN, accessToken.getToken())
|
||||
.set(TokenConstant.REFRESH_TOKEN, refreshToken.getToken())
|
||||
.set(TokenConstant.TOKEN_TYPE, TokenConstant.BEARER)
|
||||
.set(TokenConstant.EXPIRES_IN, accessToken.getExpire())
|
||||
.set(TokenConstant.DETAIL, user.getDetail())
|
||||
.set(TokenConstant.LICENSE, TokenConstant.LICENSE_NAME);
|
||||
|
||||
return token.setAccessToken(accessToken.getToken())
|
||||
.setAccessTokenExpire(accessToken.getExpire())
|
||||
.setRefreshToken(refreshToken.getToken())
|
||||
.setRefreshTokenExpire(refreshToken.getExpire());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.granter;
|
||||
|
||||
import org.springblade.core.oauth2.exception.ExceptionCode;
|
||||
import org.springblade.core.oauth2.exception.OAuth2ErrorCode;
|
||||
import org.springblade.core.oauth2.exception.UserInvalidException;
|
||||
import org.springblade.core.oauth2.handler.PasswordHandler;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.service.OAuth2Client;
|
||||
import org.springblade.core.oauth2.service.OAuth2ClientService;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
import org.springblade.core.oauth2.service.OAuth2UserService;
|
||||
import org.springblade.core.oauth2.utils.OAuth2CodeUtil;
|
||||
import org.springblade.core.oauth2.utils.OAuth2ExceptionUtil;
|
||||
import org.springblade.core.redis.cache.BladeRedis;
|
||||
import org.springblade.core.tool.utils.ObjectUtil;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* AuthorizationCodeGranter
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Component
|
||||
public class AuthorizationCodeGranter extends AbstractTokenGranter {
|
||||
|
||||
private final OAuth2UserService userService;
|
||||
private final PasswordHandler passwordHandler;
|
||||
private final BladeRedis bladeRedis;
|
||||
|
||||
public AuthorizationCodeGranter(OAuth2ClientService clientService, OAuth2UserService userService, PasswordHandler passwordHandler, BladeRedis bladeRedis) {
|
||||
super(clientService, userService, passwordHandler);
|
||||
this.userService = userService;
|
||||
this.passwordHandler = passwordHandler;
|
||||
this.bladeRedis = bladeRedis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return AUTHORIZATION_CODE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2User user(OAuth2Request request) {
|
||||
// 获取客户端信息并校验
|
||||
OAuth2Client client = client(request);
|
||||
if (!StringUtil.equals(client.getWebServerRedirectUri(), request.getRedirectUri())) {
|
||||
OAuth2ExceptionUtil.throwFromCode(OAuth2ErrorCode.INVALID_CLIENT_REDIRECT_URI);
|
||||
}
|
||||
// 根据code获取用户信息
|
||||
String code = request.getCode();
|
||||
OAuth2User user = bladeRedis.get(OAuth2CodeUtil.codeKey(code));
|
||||
// 判断用户是否存在
|
||||
if (ObjectUtil.isNotEmpty(user)) {
|
||||
// 校验用户信息
|
||||
if (!userService.validateUser(user)) {
|
||||
OAuth2ExceptionUtil.throwFromCode(OAuth2ErrorCode.INVALID_USER);
|
||||
}
|
||||
// 校验用户密码
|
||||
if ((request.isCaptchaCode() || request.isPassword()) && !passwordHandler.matches(request.getPassword(), user.getPassword())) {
|
||||
OAuth2ExceptionUtil.throwFromCode(OAuth2ErrorCode.INVALID_USER);
|
||||
}
|
||||
// 设置客户端信息
|
||||
user.setClient(client);
|
||||
// 返回user
|
||||
return Optional.ofNullable(this.enhancer)
|
||||
.map(enhancer -> enhancer.enhance(user, request))
|
||||
.orElse(user);
|
||||
}
|
||||
throw new UserInvalidException(ExceptionCode.INVALID_USER.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.granter;
|
||||
|
||||
import org.springblade.core.launch.constant.TokenConstant;
|
||||
import org.springblade.core.oauth2.handler.PasswordHandler;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Token;
|
||||
import org.springblade.core.oauth2.service.OAuth2Client;
|
||||
import org.springblade.core.oauth2.service.OAuth2ClientService;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
import org.springblade.core.oauth2.service.OAuth2UserService;
|
||||
import org.springblade.core.oauth2.service.impl.OAuth2UserDetail;
|
||||
import org.springblade.core.oauth2.utils.OAuth2Util;
|
||||
import org.springblade.core.secure.TokenInfo;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* ClientCredentialsGranter
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Component
|
||||
public class ClientCredentialsGranter extends AbstractTokenGranter {
|
||||
|
||||
public ClientCredentialsGranter(OAuth2ClientService clientService, OAuth2UserService userService, PasswordHandler passwordHandler) {
|
||||
super(clientService, userService, passwordHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return CLIENT_CREDENTIALS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2User user(OAuth2Request request) {
|
||||
OAuth2UserDetail user = new OAuth2UserDetail();
|
||||
OAuth2Client client = client(request);
|
||||
user.setClient(client);
|
||||
user.setAccount(client.getClientId());
|
||||
user.setName(client.getClientId());
|
||||
return Optional.ofNullable(this.enhancer)
|
||||
.map(enhancer -> enhancer.enhance(user, request))
|
||||
.orElse(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2Token token(OAuth2User user, OAuth2Request request) {
|
||||
TokenInfo accessToken = OAuth2Util.createClientAccessToken(user.getClient());
|
||||
|
||||
OAuth2Token token = OAuth2Token.create();
|
||||
|
||||
token.getArgs().set(TokenConstant.CLIENT_ID, user.getClient().getClientId())
|
||||
.set(TokenConstant.AVATAR, Func.toStr(user.getAvatar(), TokenConstant.DEFAULT_AVATAR))
|
||||
.set(TokenConstant.ACCESS_TOKEN, accessToken.getToken())
|
||||
.set(TokenConstant.TOKEN_TYPE, TokenConstant.BEARER)
|
||||
.set(TokenConstant.EXPIRES_IN, accessToken.getExpire())
|
||||
.set(TokenConstant.DETAIL, user.getDetail())
|
||||
.set(TokenConstant.LICENSE, TokenConstant.LICENSE_NAME);
|
||||
|
||||
return token.setAccessToken(accessToken.getToken()).setAccessTokenExpire(accessToken.getExpire());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.granter;
|
||||
|
||||
import org.springblade.core.launch.constant.TokenConstant;
|
||||
import org.springblade.core.oauth2.handler.PasswordHandler;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Token;
|
||||
import org.springblade.core.oauth2.service.OAuth2Client;
|
||||
import org.springblade.core.oauth2.service.OAuth2ClientService;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
import org.springblade.core.oauth2.service.OAuth2UserService;
|
||||
import org.springblade.core.oauth2.service.impl.OAuth2ClientDetail;
|
||||
import org.springblade.core.oauth2.service.impl.OAuth2UserDetail;
|
||||
import org.springblade.core.oauth2.utils.OAuth2Util;
|
||||
import org.springblade.core.secure.TokenInfo;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* ImplicitGranter
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Component
|
||||
public class ImplicitGranter extends AbstractTokenGranter {
|
||||
|
||||
public ImplicitGranter(OAuth2ClientService clientService, OAuth2UserService userService, PasswordHandler passwordHandler) {
|
||||
super(clientService, userService, passwordHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return IMPLICIT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2Client client(OAuth2Request request) {
|
||||
return new OAuth2ClientDetail();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2User user(OAuth2Request request) {
|
||||
OAuth2UserDetail user = new OAuth2UserDetail();
|
||||
user.setAccount(request.getUsername());
|
||||
user.setName(request.getUsername());
|
||||
return Optional.ofNullable(this.enhancer)
|
||||
.map(enhancer -> enhancer.enhance(user, request))
|
||||
.orElse(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2Token token(OAuth2User user, OAuth2Request request) {
|
||||
TokenInfo accessToken = OAuth2Util.createImplicitAccessToken(user);
|
||||
|
||||
OAuth2Token token = OAuth2Token.create();
|
||||
|
||||
token.getArgs().set(TokenConstant.USER_NAME, user.getAccount())
|
||||
.set(TokenConstant.AVATAR, Func.toStr(user.getAvatar(), TokenConstant.DEFAULT_AVATAR))
|
||||
.set(TokenConstant.ACCESS_TOKEN, accessToken.getToken())
|
||||
.set(TokenConstant.TOKEN_TYPE, TokenConstant.BEARER)
|
||||
.set(TokenConstant.EXPIRES_IN, accessToken.getExpire())
|
||||
.set(TokenConstant.DETAIL, user.getDetail())
|
||||
.set(TokenConstant.LICENSE, TokenConstant.LICENSE_NAME);
|
||||
|
||||
return token.setAccessToken(accessToken.getToken()).setAccessTokenExpire(accessToken.getExpire());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.granter;
|
||||
|
||||
import org.springblade.core.oauth2.handler.PasswordHandler;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.service.OAuth2ClientService;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
import org.springblade.core.oauth2.service.OAuth2UserService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* PasswordTokenGranter
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Component
|
||||
public class PasswordTokenGranter extends AbstractTokenGranter {
|
||||
|
||||
public PasswordTokenGranter(OAuth2ClientService clientService, OAuth2UserService userService, PasswordHandler passwordHandler) {
|
||||
super(clientService, userService, passwordHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return PASSWORD;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2User user(OAuth2Request request) {
|
||||
OAuth2User user = super.user(request);
|
||||
return Optional.ofNullable(this.enhancer)
|
||||
.map(enhancer -> enhancer.enhance(user, request))
|
||||
.orElse(user);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.granter;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import org.springblade.core.jwt.JwtUtil;
|
||||
import org.springblade.core.jwt.props.JwtProperties;
|
||||
import org.springblade.core.launch.constant.TokenConstant;
|
||||
import org.springblade.core.oauth2.exception.OAuth2ErrorCode;
|
||||
import org.springblade.core.oauth2.handler.PasswordHandler;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.service.OAuth2ClientService;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
import org.springblade.core.oauth2.service.OAuth2UserService;
|
||||
import org.springblade.core.oauth2.utils.OAuth2ExceptionUtil;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* PasswordTokenGranter
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Component
|
||||
public class RefreshTokenGranter extends PasswordTokenGranter {
|
||||
|
||||
private final JwtProperties jwtProperties;
|
||||
|
||||
public RefreshTokenGranter(OAuth2ClientService clientService, OAuth2UserService userService, PasswordHandler passwordHandler, JwtProperties jwtProperties) {
|
||||
super(clientService, userService, passwordHandler);
|
||||
this.jwtProperties = jwtProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String type() {
|
||||
return REFRESH_TOKEN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2User user(OAuth2Request request) {
|
||||
String refreshToken = request.getRefreshToken();
|
||||
Claims refreshClaims = Objects.requireNonNull(JwtUtil.parseJWT(refreshToken));
|
||||
// 校验refreshToken的合法性
|
||||
if (!judgeRefreshToken(refreshClaims, refreshToken)) {
|
||||
OAuth2ExceptionUtil.throwFromCode(OAuth2ErrorCode.INVALID_REFRESH_TOKEN);
|
||||
}
|
||||
// 校验refreshToken的格式
|
||||
String tokenType = String.valueOf(refreshClaims.get(TokenConstant.TOKEN_TYPE));
|
||||
if (!StringUtil.equals(tokenType, TokenConstant.REFRESH_TOKEN)) {
|
||||
OAuth2ExceptionUtil.throwFromCode(OAuth2ErrorCode.INVALID_REFRESH_TOKEN);
|
||||
}
|
||||
// 校验refreshToken是否可获取username
|
||||
String userId = String.valueOf(refreshClaims.get(TokenConstant.USER_ID));
|
||||
if (StringUtil.isBlank(userId)) {
|
||||
OAuth2ExceptionUtil.throwFromCode(OAuth2ErrorCode.USER_NOT_FOUND);
|
||||
}
|
||||
// 设置username
|
||||
request.setUserId(userId);
|
||||
return super.user(request);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 校验refreshToken的合法性
|
||||
*
|
||||
* @param refreshToken 待校验的refreshToken
|
||||
* @return refreshToken是否合法
|
||||
*/
|
||||
private boolean judgeRefreshToken(Claims refreshClaims, String refreshToken) {
|
||||
// 首先检查JWT是否启用单人登录模式,如果不是则直接返回true
|
||||
if (!jwtProperties.getState() || !jwtProperties.getSingle()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 解析JWT,如果无法解析则认为不合法
|
||||
return Optional.ofNullable(refreshClaims)
|
||||
.map(claims -> {
|
||||
// 从JWT claims中提取tenantId, clientId, 和 userId
|
||||
String tenantId = String.valueOf(claims.get(TokenConstant.TENANT_ID));
|
||||
String clientId = String.valueOf(claims.get(TokenConstant.CLIENT_ID));
|
||||
String userId = String.valueOf(claims.get(TokenConstant.USER_ID));
|
||||
|
||||
// 根据提取的信息和refreshToken生成新的token
|
||||
String token = JwtUtil.getRefreshToken(tenantId, clientId, userId, refreshToken);
|
||||
|
||||
// 比较新生成的token与传入的refreshToken是否一致,如果一致则认为合法
|
||||
return StringUtil.equalsIgnoreCase(token, refreshToken);
|
||||
})
|
||||
.orElse(false); // 如果claims为空,则返回false
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.granter;
|
||||
|
||||
import org.springblade.core.oauth2.constant.OAuth2GranterConstant;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Token;
|
||||
import org.springblade.core.oauth2.service.OAuth2Client;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
|
||||
/**
|
||||
* 授权认证统一接口.
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface TokenGranter extends OAuth2GranterConstant {
|
||||
|
||||
/**
|
||||
* 获取授权模式
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String type();
|
||||
|
||||
/**
|
||||
* 获取客户端信息
|
||||
*
|
||||
* @param request 授权参数
|
||||
* @return OAuth2Client
|
||||
*/
|
||||
OAuth2Client client(OAuth2Request request);
|
||||
|
||||
/**
|
||||
* 获取用户信息
|
||||
*
|
||||
* @param request 授权参数
|
||||
* @return OAuth2User
|
||||
*/
|
||||
OAuth2User user(OAuth2Request request);
|
||||
|
||||
/**
|
||||
* 创建令牌
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param request 授权参数
|
||||
* @return OAuth2Token
|
||||
*/
|
||||
OAuth2Token token(OAuth2User user, OAuth2Request request);
|
||||
|
||||
/**
|
||||
* 自定义增强
|
||||
*
|
||||
* @param enhancer enhancer
|
||||
*/
|
||||
void enhancer(TokenGranterEnhancer enhancer);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.granter;
|
||||
|
||||
import org.springblade.core.oauth2.constant.OAuth2GranterConstant;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
|
||||
/**
|
||||
* TokenGranterEnhancer
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface TokenGranterEnhancer extends OAuth2GranterConstant {
|
||||
|
||||
/**
|
||||
* 获取授权模式
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String type();
|
||||
|
||||
/**
|
||||
* 增强用户令牌
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param request 授权参数
|
||||
* @return OAuth2User
|
||||
*/
|
||||
OAuth2User enhance(OAuth2User user, OAuth2Request request);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.granter;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springblade.core.oauth2.exception.GranterInvalidException;
|
||||
import org.springblade.core.oauth2.props.OAuth2Properties;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import static org.springblade.core.oauth2.constant.OAuth2GranterConstant.*;
|
||||
import static org.springblade.core.oauth2.exception.OAuth2ErrorMessage.INVALID_GRANT_TYPE;
|
||||
|
||||
/**
|
||||
* TokenGranterFactory
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class TokenGranterFactory {
|
||||
|
||||
/**
|
||||
* TokenGranter 集合
|
||||
*/
|
||||
private final List<TokenGranter> tokenGranters;
|
||||
|
||||
/**
|
||||
* TokenGranterEnhancer 集合
|
||||
*/
|
||||
private final List<TokenGranterEnhancer> tokenGranterEnhancers;
|
||||
|
||||
/**
|
||||
* OAuth2 属性配置
|
||||
*/
|
||||
private final OAuth2Properties properties;
|
||||
|
||||
/**
|
||||
* TokenGranter 缓存池,使用 ConcurrentHashMap 保证线程安全。
|
||||
*/
|
||||
private static final Map<String, TokenGranter> GRANTER_POOL = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* 根据授权模式获取 TokenGranter,如果缓存中不存在,则尝试创建。
|
||||
*
|
||||
* @param grantType 授权模式
|
||||
* @return TokenGranter 实例
|
||||
* @throws IllegalArgumentException 如果请求的授权类型不支持
|
||||
*/
|
||||
public TokenGranter create(String grantType) {
|
||||
// 使用 computeIfAbsent 实现延迟加载
|
||||
return GRANTER_POOL.computeIfAbsent(grantType, this::initializeTokenGranter);
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试根据授权类型初始化 TokenGranter。
|
||||
*
|
||||
* @param grantType 授权模式
|
||||
* @return 初始化的 TokenGranter
|
||||
* @throws GranterInvalidException 如果无法识别授权类型
|
||||
*/
|
||||
private TokenGranter initializeTokenGranter(String grantType) {
|
||||
// 根据授权类型查找对应的 TokenGranter 并应用第一个找到的增强类
|
||||
return tokenGranters.stream()
|
||||
.filter(granter -> granter.type().equals(grantType) && isGranterEnabled(granter))
|
||||
.peek(granter -> tokenGranterEnhancers.stream()
|
||||
.filter(enhancer -> enhancer.type().equals(grantType))
|
||||
.findFirst()
|
||||
.ifPresent(granter::enhancer))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new GranterInvalidException(String.format(INVALID_GRANT_TYPE, grantType)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断 TokenGranter 是否启用。
|
||||
*
|
||||
* @param granter TokenGranter 实例
|
||||
* @return 是否启用
|
||||
*/
|
||||
private boolean isGranterEnabled(TokenGranter granter) {
|
||||
return switch (granter.type()) {
|
||||
case AUTHORIZATION_CODE -> properties.getGranter().getAuthorizationCode();
|
||||
case PASSWORD -> properties.getGranter().getPassword();
|
||||
case REFRESH_TOKEN -> properties.getGranter().getRefreshToken();
|
||||
case CLIENT_CREDENTIALS -> properties.getGranter().getClientCredentials();
|
||||
case IMPLICIT -> properties.getGranter().getImplicit();
|
||||
case CAPTCHA -> properties.getGranter().getCaptcha();
|
||||
case SMS_CODE -> properties.getGranter().getSmsCode();
|
||||
case WECHAT_APPLET -> properties.getGranter().getWechatApplet();
|
||||
case SOCIAL -> properties.getGranter().getSocial();
|
||||
case REGISTER -> properties.getGranter().getRegister();
|
||||
default -> true;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.handler;
|
||||
|
||||
import org.springblade.core.oauth2.exception.ExceptionCode;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Validation;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
|
||||
/**
|
||||
* AbstractAuthorizationHandler
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public abstract class AbstractAuthorizationHandler implements AuthorizationHandler {
|
||||
|
||||
/**
|
||||
* 认证校验
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param request 请求信息
|
||||
* @return boolean
|
||||
*/
|
||||
@Override
|
||||
public OAuth2Validation authValidation(OAuth2User user, OAuth2Request request) {
|
||||
if (request.isClientCredentials() || request.isImplicit() || request.isSocial()) {
|
||||
return new OAuth2Validation();
|
||||
}
|
||||
if (Func.hasEmpty(user, user.getUserId())) {
|
||||
return buildValidationFailure(ExceptionCode.USER_NOT_FOUND);
|
||||
}
|
||||
if (Func.isEmpty(user.getAuthorities())) {
|
||||
return buildValidationFailure(ExceptionCode.UNAUTHORIZED_USER);
|
||||
}
|
||||
return new OAuth2Validation();
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证成功回调
|
||||
*
|
||||
* @param user 用户信息
|
||||
*/
|
||||
@Override
|
||||
public abstract void authSuccessful(OAuth2User user, OAuth2Request request);
|
||||
|
||||
/**
|
||||
* 认证失败回调
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param validation 失败信息
|
||||
*/
|
||||
@Override
|
||||
public abstract void authFailure(OAuth2User user, OAuth2Request request, OAuth2Validation validation);
|
||||
|
||||
/**
|
||||
* 构建认证失败返回
|
||||
*
|
||||
* @param errorCode 错误码
|
||||
* @return 认证结果
|
||||
*/
|
||||
public OAuth2Validation buildValidationFailure(ExceptionCode errorCode) {
|
||||
return new OAuth2Validation().setSuccess(false)
|
||||
.setCode(errorCode.getCode())
|
||||
.setMessage(errorCode.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.handler;
|
||||
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Validation;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
|
||||
/**
|
||||
* OAuth2AuthorizationHandler
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface AuthorizationHandler {
|
||||
|
||||
/**
|
||||
* 认证校验
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param request 请求信息
|
||||
* @return boolean
|
||||
*/
|
||||
OAuth2Validation authValidation(OAuth2User user, OAuth2Request request);
|
||||
|
||||
/**
|
||||
* 认证成功回调
|
||||
*
|
||||
* @param user 用户信息
|
||||
*/
|
||||
void authSuccessful(OAuth2User user, OAuth2Request request);
|
||||
|
||||
/**
|
||||
* 认证失败回调
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param validation 失败信息
|
||||
*/
|
||||
void authFailure(OAuth2User user, OAuth2Request request, OAuth2Validation validation);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.handler;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Validation;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
|
||||
/**
|
||||
* AbstractAuthorizationHandler
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Slf4j
|
||||
public class OAuth2AuthorizationHandler extends AbstractAuthorizationHandler {
|
||||
|
||||
/**
|
||||
* 认证成功回调
|
||||
*
|
||||
* @param user 用户信息
|
||||
*/
|
||||
@Override
|
||||
public void authSuccessful(OAuth2User user, OAuth2Request request) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 认证失败回调
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param validation 失败信息
|
||||
*/
|
||||
@Override
|
||||
public void authFailure(OAuth2User user, OAuth2Request request, OAuth2Validation validation) {
|
||||
log.error("用户:{},认证失败,失败原因:{}", user.getAccount(), validation.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.handler;
|
||||
|
||||
import org.springblade.core.tool.utils.DigestUtil;
|
||||
|
||||
/**
|
||||
* BladePasswordHandler
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public class OAuth2PasswordHandler implements PasswordHandler {
|
||||
|
||||
/**
|
||||
* 判断密码是否匹配
|
||||
*
|
||||
* @param rawPassword 请求时提交的原密码
|
||||
* @param encodedPassword 数据库加密后的密码
|
||||
* @return boolean
|
||||
*/
|
||||
@Override
|
||||
public boolean matches(String rawPassword, String encodedPassword) {
|
||||
return encodedPassword.equals(encode(rawPassword));
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密密码规则
|
||||
*
|
||||
* @param rawPassword 密码
|
||||
* @return 加密后的密码
|
||||
*/
|
||||
@Override
|
||||
public String encode(String rawPassword) {
|
||||
return DigestUtil.hex(rawPassword);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.handler;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springblade.core.jwt.JwtUtil;
|
||||
import org.springblade.core.jwt.props.JwtProperties;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Token;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
|
||||
/**
|
||||
* BladeTokenHandler
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class OAuth2TokenHandler implements TokenHandler {
|
||||
|
||||
private final JwtProperties properties;
|
||||
|
||||
/**
|
||||
* 令牌增强
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param token 令牌信息
|
||||
* @param request 授权参数
|
||||
* @return OAuth2Token
|
||||
*/
|
||||
@Override
|
||||
public OAuth2Token enhance(OAuth2User user, OAuth2Token token, OAuth2Request request) {
|
||||
|
||||
//令牌状态配置, 仅在生成AccessToken时候执行
|
||||
if (properties.getState() && token.hasAccessToken()) {
|
||||
JwtUtil.addAccessToken(
|
||||
user.getTenantId(),
|
||||
user.getClient().getClientId(),
|
||||
user.getUserId(),
|
||||
token.getAccessToken(),
|
||||
token.getAccessTokenExpire()
|
||||
);
|
||||
}
|
||||
//令牌状态配置, 仅在生成RefreshToken时候执行
|
||||
if (properties.getState() && properties.getSingle() && token.hasRefreshToken()) {
|
||||
JwtUtil.addRefreshToken(
|
||||
user.getTenantId(),
|
||||
user.getClient().getClientId(),
|
||||
user.getUserId(),
|
||||
token.getRefreshToken(),
|
||||
token.getRefreshTokenExpire()
|
||||
);
|
||||
}
|
||||
|
||||
// 返回令牌
|
||||
return token;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.handler;
|
||||
|
||||
/**
|
||||
* PasswordHandler
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface PasswordHandler {
|
||||
|
||||
/**
|
||||
* 判断密码是否匹配
|
||||
*
|
||||
* @param rawPassword 请求时提交的原密码
|
||||
* @param encodedPassword 数据库加密后的密码
|
||||
* @return boolean
|
||||
*/
|
||||
boolean matches(String rawPassword, String encodedPassword);
|
||||
|
||||
/**
|
||||
* 加密密码规则
|
||||
*
|
||||
* @param rawPassword 密码
|
||||
* @return 加密后的密码
|
||||
*/
|
||||
String encode(String rawPassword);
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.handler;
|
||||
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Token;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
|
||||
/**
|
||||
* TokenHandler
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface TokenHandler {
|
||||
|
||||
/**
|
||||
* 令牌增强
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @param token 令牌信息
|
||||
* @param request 授权参数
|
||||
* @return OAuth2Token
|
||||
*/
|
||||
OAuth2Token enhance(OAuth2User user, OAuth2Token token, OAuth2Request request);
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.props;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* OAuth2Property
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ConfigurationProperties(OAuth2Properties.PREFIX)
|
||||
public class OAuth2Properties {
|
||||
/**
|
||||
* 配置前缀
|
||||
*/
|
||||
public static final String PREFIX = "blade.oauth2";
|
||||
|
||||
/**
|
||||
* 是否开启OAuth2
|
||||
*/
|
||||
private Boolean enabled = true;
|
||||
|
||||
/**
|
||||
* code缓存时间
|
||||
*/
|
||||
private long codeTimeout = 10 * 60L;
|
||||
|
||||
/**
|
||||
* 授权模式
|
||||
*/
|
||||
private Granter granter = new Granter();
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public static class Granter {
|
||||
/**
|
||||
* 是否开启授权码模式
|
||||
*/
|
||||
private Boolean authorizationCode = true;
|
||||
/**
|
||||
* 是否开启验证码模式
|
||||
*/
|
||||
private Boolean captcha = true;
|
||||
/**
|
||||
* 是否开启密码模式
|
||||
*/
|
||||
private Boolean password = true;
|
||||
/**
|
||||
* 是否开启刷新token模式
|
||||
*/
|
||||
private Boolean refreshToken = true;
|
||||
/**
|
||||
* 是否开启客户端模式
|
||||
*/
|
||||
private Boolean clientCredentials = true;
|
||||
/**
|
||||
* 是否开启简化模式
|
||||
*/
|
||||
private Boolean implicit = true;
|
||||
/**
|
||||
* 是否手机验证码模式
|
||||
*/
|
||||
private Boolean smsCode = true;
|
||||
/**
|
||||
* 是否开启微信小程序模式
|
||||
*/
|
||||
private Boolean wechatApplet = true;
|
||||
/**
|
||||
* 是否开启开放平台模式
|
||||
*/
|
||||
private Boolean social = true;
|
||||
/**
|
||||
* 是否开启注册模式
|
||||
*/
|
||||
private Boolean register = true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.provider;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.Data;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.springblade.core.oauth2.constant.OAuth2ParameterConstant.*;
|
||||
|
||||
/**
|
||||
* OAuth2AuthorizationRequest
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Data
|
||||
public class OAuth2AuthorizationRequest implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String responseType;
|
||||
private String tenantId;
|
||||
private String clientId;
|
||||
private String redirectUri;
|
||||
private String scope;
|
||||
private String state;
|
||||
|
||||
/**
|
||||
* 实例化
|
||||
*/
|
||||
public static OAuth2AuthorizationRequest create() {
|
||||
return new OAuth2AuthorizationRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建参数
|
||||
*
|
||||
* @return OAuth2AuthorizationRequest
|
||||
*/
|
||||
public OAuth2AuthorizationRequest buildParameters() {
|
||||
HttpServletRequest request = Objects.requireNonNull(WebUtil.getRequest());
|
||||
this.responseType = request.getParameter(RESPONSE_TYPE);
|
||||
this.tenantId = request.getParameter(TENANT_ID);
|
||||
this.clientId = request.getParameter(CLIENT_ID);
|
||||
this.redirectUri = request.getParameter(REDIRECT_URI);
|
||||
this.scope = request.getParameter(SCOPE);
|
||||
this.state = request.getParameter(STATE);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取参数
|
||||
*
|
||||
* @return Map
|
||||
*/
|
||||
public Map<String, String> getParameters() {
|
||||
Map<String, String> parameters = new HashMap<>();
|
||||
parameters.put(RESPONSE_TYPE, this.responseType);
|
||||
parameters.put(CLIENT_ID, this.clientId);
|
||||
parameters.put(REDIRECT_URI, this.redirectUri);
|
||||
if (scope != null) {
|
||||
parameters.put(SCOPE, this.scope);
|
||||
}
|
||||
if (this.tenantId != null) {
|
||||
parameters.put(STATE, this.tenantId);
|
||||
}
|
||||
if (state != null) {
|
||||
parameters.put(STATE, this.state);
|
||||
}
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public String getState() {
|
||||
return StringUtil.isBlank(this.state) ? this.tenantId : this.state;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,386 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.provider;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.Data;
|
||||
import org.springblade.core.oauth2.utils.OAuth2Util;
|
||||
import org.springblade.core.tool.support.Kv;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.springblade.core.oauth2.constant.OAuth2GranterConstant.PASSWORD;
|
||||
import static org.springblade.core.oauth2.constant.OAuth2GranterConstant.REFRESH_TOKEN;
|
||||
import static org.springblade.core.oauth2.constant.OAuth2GranterConstant.*;
|
||||
import static org.springblade.core.oauth2.constant.OAuth2ParameterConstant.*;
|
||||
import static org.springblade.core.oauth2.constant.OAuth2TokenConstant.*;
|
||||
|
||||
/**
|
||||
* OAuth2参数类
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Data
|
||||
public class OAuth2Request {
|
||||
|
||||
/**
|
||||
* 实例化
|
||||
*/
|
||||
public static OAuth2Request create() {
|
||||
return new OAuth2Request();
|
||||
}
|
||||
|
||||
/**
|
||||
* 请求参数
|
||||
*/
|
||||
private Kv parameterArgs = Kv.create();
|
||||
|
||||
/**
|
||||
* 头部参数
|
||||
*/
|
||||
private Kv headerArgs = Kv.create();
|
||||
|
||||
/**
|
||||
* 自动构建参数
|
||||
*
|
||||
* @return OAuth2Request
|
||||
*/
|
||||
public OAuth2Request buildArgs() {
|
||||
return this.buildParameterArgs().buildHeaderArgs();
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动构建请求头参数
|
||||
*
|
||||
* @return OAuth2Request
|
||||
*/
|
||||
public OAuth2Request buildParameterArgs() {
|
||||
HttpServletRequest request = Objects.requireNonNull(WebUtil.getRequest());
|
||||
Arrays.stream(new String[]{
|
||||
CLIENT_ID, CLIENT_SECRET, ACCESS_TOKEN, REFRESH_TOKEN, TENANT_ID, USERNAME, PASSWORD, NAME, PHONE, EMAIL, GRANT_TYPE, SCOPE, REDIRECT_URI, RESPONSE_TYPE, CODE, STATE, SOURCE
|
||||
}).forEach(param -> Optional.ofNullable(request.getParameter(param)).ifPresent(value -> parameterArgs.set(param, value)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动构建头部参数
|
||||
*
|
||||
* @return OAuth2Request
|
||||
*/
|
||||
public OAuth2Request buildHeaderArgs() {
|
||||
HttpServletRequest request = Objects.requireNonNull(WebUtil.getRequest());
|
||||
Arrays.stream(new String[]{
|
||||
HEADER_AUTHORIZATION, TENANT_HEADER, USER_HEADER, ROLE_HEADER, DEPT_HEADER, USER_TYPE_HEADER, CAPTCHA_HEADER_KEY, CAPTCHA_HEADER_CODE
|
||||
}).forEach(param -> Optional.ofNullable(request.getHeader(param)).ifPresent(value -> headerArgs.set(param, value)));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户端ID
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getClientIdFromParameter() {
|
||||
return parameterArgs.getStr(CLIENT_ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户端密钥
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getClientSecretFromParameter() {
|
||||
return parameterArgs.getStr(CLIENT_SECRET);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取客户端ID和密钥
|
||||
*
|
||||
* @return String[]
|
||||
*/
|
||||
public String[] getClientFromAuthorization() {
|
||||
return OAuth2Util.extractAndDecodeAuthorization();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取令牌
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getToken() {
|
||||
return headerArgs.getStr(TOKEN_HEADER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取租户编号
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getTenantId() {
|
||||
if (StringUtil.isBlank(headerArgs.getStr(TENANT_HEADER))) {
|
||||
return parameterArgs.getStr(TENANT_ID);
|
||||
}
|
||||
return headerArgs.getStr(TENANT_HEADER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户ID
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getUserId() {
|
||||
return headerArgs.getStr(USER_HEADER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户名
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getUsername() {
|
||||
return parameterArgs.getStr(USERNAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取密码
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getPassword() {
|
||||
return parameterArgs.getStr(PASSWORD);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户名字
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getName() {
|
||||
return parameterArgs.getStr(NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取手机号
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getPhone() {
|
||||
return parameterArgs.getStr(PHONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取电子游戏
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getEmail() {
|
||||
return parameterArgs.getStr(EMAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户名
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getUserType() {
|
||||
return headerArgs.getStr(USER_TYPE_HEADER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户部门
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getUserDept() {
|
||||
return headerArgs.getStr(DEPT_HEADER);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取用户角色
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getUserRole() {
|
||||
return headerArgs.getStr(ROLE_HEADER);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取验证码key
|
||||
*/
|
||||
public String getCaptchaKey() {
|
||||
return headerArgs.getStr(CAPTCHA_HEADER_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取验证码code
|
||||
*/
|
||||
public String getCaptchaCode() {
|
||||
return headerArgs.getStr(CAPTCHA_HEADER_CODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取授权类型
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getGrantType() {
|
||||
return parameterArgs.getStr(GRANT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取刷新令牌
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getRefreshToken() {
|
||||
return parameterArgs.getStr(REFRESH_TOKEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取验证code
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getCode() {
|
||||
return parameterArgs.getStr(CODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取状态
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getState() {
|
||||
return parameterArgs.getStr(STATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取来源
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getSource() {
|
||||
return parameterArgs.getStr(SOURCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取回调地址
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
public String getRedirectUri() {
|
||||
return parameterArgs.getStr(REDIRECT_URI);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否密码模式
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public Boolean isPassword() {
|
||||
return PASSWORD.equals(getGrantType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否刷新模式
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public Boolean isRefreshToken() {
|
||||
return REFRESH_TOKEN.equals(getGrantType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否验证码模式
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public Boolean isCaptchaCode() {
|
||||
return CAPTCHA.equals(getGrantType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否密码模式
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public Boolean isClientCredentials() {
|
||||
return CLIENT_CREDENTIALS.equals(getGrantType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否简化模式
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public Boolean isImplicit() {
|
||||
return IMPLICIT.equals(getGrantType());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 是否开放平台模式
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public Boolean isSocial() {
|
||||
return SOCIAL.equals(getGrantType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置租户ID
|
||||
*
|
||||
* @param tenantId 户ID
|
||||
*/
|
||||
public void setTenantId(String tenantId) {
|
||||
this.headerArgs.set(TENANT_HEADER, tenantId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户ID
|
||||
*
|
||||
* @param userId 用户ID
|
||||
*/
|
||||
public void setUserId(String userId) {
|
||||
this.headerArgs.set(USER_HEADER, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置用户名
|
||||
*
|
||||
* @param username 用户名
|
||||
*/
|
||||
public void setUsername(String username) {
|
||||
this.parameterArgs.set(USERNAME, username);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.provider;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springblade.core.tool.support.Kv;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
import static org.springblade.core.oauth2.constant.OAuth2ResponseConstant.*;
|
||||
|
||||
/**
|
||||
* OAuth2Response
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Data
|
||||
public class OAuth2Response implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 实例化
|
||||
*/
|
||||
public static OAuth2Response create() {
|
||||
return new OAuth2Response();
|
||||
}
|
||||
|
||||
/**
|
||||
* 响应参数
|
||||
*/
|
||||
private Kv args = Kv.create();
|
||||
|
||||
public Kv of(boolean success, int errorCode, String errorDescription) {
|
||||
args.set(SUCCESS, success);
|
||||
args.set(ERROR_CODE, errorCode);
|
||||
args.set(ERROR_DESCRIPTION, errorDescription);
|
||||
return args;
|
||||
|
||||
}
|
||||
|
||||
public Kv ofValidation(OAuth2Validation validation) {
|
||||
args.set(SUCCESS, validation.isSuccess());
|
||||
args.set(ERROR_CODE, validation.getCode());
|
||||
args.set(ERROR_DESCRIPTION, validation.getMessage());
|
||||
return args;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.provider;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.springblade.core.tool.support.Kv;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* OAuth2Token
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2Token implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 实例化
|
||||
*/
|
||||
public static OAuth2Token create() {
|
||||
return new OAuth2Token();
|
||||
}
|
||||
|
||||
/**
|
||||
* 令牌值
|
||||
*/
|
||||
private String accessToken;
|
||||
|
||||
/**
|
||||
* 刷新令牌值
|
||||
*/
|
||||
private String refreshToken;
|
||||
|
||||
/**
|
||||
* 令牌过期秒数
|
||||
*/
|
||||
private int accessTokenExpire;
|
||||
|
||||
/**
|
||||
* 刷新令牌过期秒数
|
||||
*/
|
||||
private int refreshTokenExpire;
|
||||
|
||||
/**
|
||||
* 令牌参数
|
||||
*/
|
||||
private Kv args = Kv.create();
|
||||
|
||||
|
||||
/**
|
||||
* 是否包含令牌
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public Boolean hasAccessToken() {
|
||||
return StringUtil.isNotBlank(accessToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否包含刷新令牌
|
||||
*
|
||||
* @return Boolean
|
||||
*/
|
||||
public Boolean hasRefreshToken() {
|
||||
return StringUtil.isNotBlank(refreshToken);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.provider;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* OAuth2Validation
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class OAuth2Validation {
|
||||
|
||||
/**
|
||||
* 是否成功
|
||||
*/
|
||||
boolean success = true;
|
||||
|
||||
/**
|
||||
* 状态码
|
||||
*/
|
||||
int code = 1000;
|
||||
|
||||
/**
|
||||
* 验证信息
|
||||
*/
|
||||
String message = "认证通过";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.service;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 多终端详情接口
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface OAuth2Client extends Serializable {
|
||||
|
||||
/**
|
||||
* 获取客户端ID.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getClientId();
|
||||
|
||||
/**
|
||||
* 获取客户端密钥.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getClientSecret();
|
||||
|
||||
/**
|
||||
* 获取资源集合.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getResourceIds();
|
||||
|
||||
/**
|
||||
* 获取授权范围.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getScope();
|
||||
|
||||
/**
|
||||
* 获取授权类型.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getAuthorizedGrantTypes();
|
||||
|
||||
/**
|
||||
* 获取回调地址.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getWebServerRedirectUri();
|
||||
|
||||
/**
|
||||
* 获取权限.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getAuthorities();
|
||||
|
||||
/**
|
||||
* 获取访问令牌有效期.
|
||||
*
|
||||
* @return Integer
|
||||
*/
|
||||
Integer getAccessTokenValidity();
|
||||
|
||||
/**
|
||||
* 获取刷新令牌有效期.
|
||||
*
|
||||
* @return Integer
|
||||
*/
|
||||
Integer getRefreshTokenValidity();
|
||||
|
||||
/**
|
||||
* 获取附加信息.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getAdditionalInformation();
|
||||
|
||||
/**
|
||||
* 获取自动授权.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getAutoapprove();
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.service;
|
||||
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
|
||||
/**
|
||||
* 多终端注册接口
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface OAuth2ClientService {
|
||||
|
||||
/**
|
||||
* 根据clientId获取Client详情
|
||||
*
|
||||
* @param clientId 客户端id
|
||||
* @return 客户端信息
|
||||
*/
|
||||
OAuth2Client loadByClientId(String clientId);
|
||||
|
||||
/**
|
||||
* 根据clientId获取Client详情
|
||||
*
|
||||
* @param clientId 客户端id
|
||||
* @param request 授权参数
|
||||
* @return 客户端信息
|
||||
*/
|
||||
OAuth2Client loadByClientId(String clientId, OAuth2Request request);
|
||||
|
||||
/**
|
||||
* 验证Client信息
|
||||
*
|
||||
* @param client client信息
|
||||
* @param clientId 客户端id
|
||||
* @param clientSecret 客户端密钥
|
||||
* @return boolean
|
||||
*/
|
||||
boolean validateClient(OAuth2Client client, String clientId, String clientSecret);
|
||||
|
||||
/**
|
||||
* 验证Client信息
|
||||
*
|
||||
* @param client client信息
|
||||
* @param redirectUri 回调地址
|
||||
* @return boolean
|
||||
*/
|
||||
boolean validateRedirectUri(OAuth2Client client, String redirectUri);
|
||||
|
||||
/**
|
||||
* 验证授权类型
|
||||
*
|
||||
* @param client client信息
|
||||
* @param grantType 授权类型
|
||||
* @return boolean
|
||||
*/
|
||||
boolean validateGranter(OAuth2Client client, String grantType);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.service;
|
||||
|
||||
import org.springblade.core.tool.support.Kv;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户基础信息
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface OAuth2User extends Serializable {
|
||||
|
||||
/**
|
||||
* 获取用户ID.
|
||||
*
|
||||
* @return Long
|
||||
*/
|
||||
String getUserId();
|
||||
|
||||
/**
|
||||
* 获取租户ID.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getTenantId();
|
||||
|
||||
/**
|
||||
* 获取第三方认证ID.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getOauthId();
|
||||
|
||||
/**
|
||||
* 获取昵称.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* 获取真名.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getRealName();
|
||||
|
||||
/**
|
||||
* 获取账号.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getAccount();
|
||||
|
||||
/**
|
||||
* 获取密码.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getPassword();
|
||||
|
||||
/**
|
||||
* 获取手机.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getPhone();
|
||||
|
||||
/**
|
||||
* 获取邮箱.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getEmail();
|
||||
|
||||
/**
|
||||
* 获取部门ID.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getDeptId();
|
||||
|
||||
/**
|
||||
* 获取岗位ID.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getPostId();
|
||||
|
||||
/**
|
||||
* 获取角色ID.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getRoleId();
|
||||
|
||||
/**
|
||||
* 获取角色名.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getRoleName();
|
||||
|
||||
/**
|
||||
* 获取头像.
|
||||
*
|
||||
* @return String
|
||||
*/
|
||||
String getAvatar();
|
||||
|
||||
/**
|
||||
* 获取权限集合.
|
||||
*
|
||||
* @return List<String>
|
||||
*/
|
||||
List<String> getPermissions();
|
||||
|
||||
/**
|
||||
* 获取角色集合.
|
||||
*
|
||||
* @return List<String>
|
||||
*/
|
||||
List<String> getAuthorities();
|
||||
|
||||
/**
|
||||
* 获取客户端信息.
|
||||
*
|
||||
* @return OAuth2Client
|
||||
*/
|
||||
OAuth2Client getClient();
|
||||
|
||||
/**
|
||||
* 设置客户端信息.
|
||||
*/
|
||||
void setClient(OAuth2Client client);
|
||||
|
||||
/**
|
||||
* 获取用户详情.
|
||||
*
|
||||
* @return Kv
|
||||
*/
|
||||
Kv getDetail();
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.service;
|
||||
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
|
||||
/**
|
||||
* OAuth2UserService
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public interface OAuth2UserService {
|
||||
|
||||
/**
|
||||
* 根据用户名获取用户信息
|
||||
*
|
||||
* @param userId 用户ID
|
||||
* @param request 授权参数
|
||||
* @return 用户信息
|
||||
*/
|
||||
OAuth2User loadByUserId(String userId, OAuth2Request request);
|
||||
|
||||
/**
|
||||
* 根据用户名获取用户信息
|
||||
*
|
||||
* @param username 用户名
|
||||
* @param request 授权参数
|
||||
* @return 用户信息
|
||||
*/
|
||||
OAuth2User loadByUsername(String username, OAuth2Request request);
|
||||
|
||||
/**
|
||||
* 校验用户信息
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return 是否通过
|
||||
*/
|
||||
boolean validateUser(OAuth2User user);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.service.impl;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springblade.core.oauth2.service.OAuth2Client;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 客户端详情
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "oauth2客户端实体类")
|
||||
public class OAuth2ClientDetail implements OAuth2Client {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 客户端id
|
||||
*/
|
||||
@Schema(description = "客户端id")
|
||||
private String clientId;
|
||||
/**
|
||||
* 客户端密钥
|
||||
*/
|
||||
@Schema(description = "客户端密钥")
|
||||
private String clientSecret;
|
||||
/**
|
||||
* 资源集合
|
||||
*/
|
||||
@Schema(description = "资源集合")
|
||||
private String resourceIds;
|
||||
/**
|
||||
* 授权范围
|
||||
*/
|
||||
@Schema(description = "授权范围")
|
||||
private String scope;
|
||||
/**
|
||||
* 授权类型
|
||||
*/
|
||||
@Schema(description = "授权类型")
|
||||
private String authorizedGrantTypes;
|
||||
/**
|
||||
* 回调地址
|
||||
*/
|
||||
@Schema(description = "回调地址")
|
||||
private String webServerRedirectUri;
|
||||
/**
|
||||
* 权限
|
||||
*/
|
||||
@Schema(description = "权限")
|
||||
private String authorities;
|
||||
/**
|
||||
* 令牌过期秒数
|
||||
*/
|
||||
@Schema(description = "令牌过期秒数")
|
||||
private Integer accessTokenValidity;
|
||||
/**
|
||||
* 刷新令牌过期秒数
|
||||
*/
|
||||
@Schema(description = "刷新令牌过期秒数")
|
||||
private Integer refreshTokenValidity;
|
||||
/**
|
||||
* 附加说明
|
||||
*/
|
||||
@Schema(description = "附加说明")
|
||||
private String additionalInformation;
|
||||
/**
|
||||
* 自动授权
|
||||
*/
|
||||
@Schema(description = "自动授权")
|
||||
private String autoapprove;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.service.impl;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springblade.core.oauth2.constant.OAuth2ClientConstant;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.service.OAuth2Client;
|
||||
import org.springblade.core.oauth2.service.OAuth2ClientService;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.StringPool;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 获取客户端详情
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class OAuth2ClientDetailService implements OAuth2ClientService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Override
|
||||
public OAuth2Client loadByClientId(String clientId) {
|
||||
return loadByClientId(clientId, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2Client loadByClientId(String clientId, OAuth2Request request) {
|
||||
try {
|
||||
return jdbcTemplate.queryForObject(OAuth2ClientConstant.DEFAULT_SELECT_STATEMENT, new BeanPropertyRowMapper<>(OAuth2ClientDetail.class), clientId);
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateClient(OAuth2Client client, String clientId, String clientSecret) {
|
||||
return Optional.ofNullable(client)
|
||||
.map(c -> StringUtil.equals(clientId, c.getClientId()) && StringUtil.equals(clientSecret, c.getClientSecret()))
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateRedirectUri(OAuth2Client client, String redirectUri) {
|
||||
return Optional.ofNullable(client)
|
||||
.map(c -> StringUtil.equals(redirectUri, c.getWebServerRedirectUri()))
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateGranter(OAuth2Client client, String grantType) {
|
||||
return Optional.ofNullable(client)
|
||||
.map(c -> Arrays.stream(Func.split(c.getAuthorizedGrantTypes(), StringPool.COMMA))
|
||||
.anyMatch(s -> s.trim().equals(grantType)))
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.service.impl;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.springblade.core.oauth2.service.OAuth2Client;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
import org.springblade.core.tool.support.Kv;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户详情
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "oauth2用户实体类")
|
||||
public class OAuth2UserDetail implements OAuth2User {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
@Schema(description = "用户id")
|
||||
private String userId;
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
@Schema(description = "租户ID")
|
||||
private String tenantId;
|
||||
/**
|
||||
* 第三方认证ID
|
||||
*/
|
||||
@Schema(description = "第三方认证ID")
|
||||
private String oauthId;
|
||||
/**
|
||||
* 昵称
|
||||
*/
|
||||
@Schema(description = "昵称")
|
||||
private String name;
|
||||
/**
|
||||
* 真名
|
||||
*/
|
||||
@Schema(description = "真名")
|
||||
private String realName;
|
||||
/**
|
||||
* 账号
|
||||
*/
|
||||
@Schema(description = "账号")
|
||||
private String account;
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
@JsonIgnore
|
||||
@Schema(description = "密码")
|
||||
private String password;
|
||||
/**
|
||||
* 手机
|
||||
*/
|
||||
@Schema(description = "手机")
|
||||
private String phone;
|
||||
/**
|
||||
* 邮箱
|
||||
*/
|
||||
@Schema(description = "邮箱")
|
||||
private String email;
|
||||
/**
|
||||
* 部门id
|
||||
*/
|
||||
@Schema(description = "部门id")
|
||||
private String deptId;
|
||||
/**
|
||||
* 岗位id
|
||||
*/
|
||||
@Schema(description = "岗位id")
|
||||
private String postId;
|
||||
/**
|
||||
* 角色id
|
||||
*/
|
||||
@Schema(description = "角色id")
|
||||
private String roleId;
|
||||
/**
|
||||
* 角色名
|
||||
*/
|
||||
@Schema(description = "角色名")
|
||||
private String roleName;
|
||||
/**
|
||||
* 头像
|
||||
*/
|
||||
@Schema(description = "头像")
|
||||
private String avatar;
|
||||
|
||||
/**
|
||||
* 权限标识集合
|
||||
*/
|
||||
@Schema(description = "权限集合")
|
||||
private List<String> permissions;
|
||||
|
||||
/**
|
||||
* 角色集合
|
||||
*/
|
||||
@Schema(description = "角色集合")
|
||||
private List<String> authorities;
|
||||
|
||||
/**
|
||||
* 客户端
|
||||
*/
|
||||
@Schema(description = "客户端")
|
||||
private OAuth2Client client;
|
||||
|
||||
/**
|
||||
* 用户详情
|
||||
*/
|
||||
@Schema(description = "用户详情")
|
||||
private Kv detail;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.service.impl;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springblade.core.oauth2.constant.OAuth2UserConstant;
|
||||
import org.springblade.core.oauth2.provider.OAuth2Request;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
import org.springblade.core.oauth2.service.OAuth2UserService;
|
||||
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* 获取用户详情
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class OAuth2UserDetailService implements OAuth2UserService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Override
|
||||
public OAuth2User loadByUserId(String userId, OAuth2Request request) {
|
||||
try {
|
||||
return jdbcTemplate.queryForObject(OAuth2UserConstant.DEFAULT_USERID_SELECT_STATEMENT, new BeanPropertyRowMapper<>(OAuth2UserDetail.class), userId);
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2User loadByUsername(String username, OAuth2Request request) {
|
||||
try {
|
||||
return jdbcTemplate.queryForObject(OAuth2UserConstant.DEFAULT_USERNAME_SELECT_STATEMENT, new BeanPropertyRowMapper<>(OAuth2UserDetail.class), username);
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateUser(OAuth2User user) {
|
||||
return Optional.ofNullable(user)
|
||||
.filter(u -> u.getUserId() != null && !u.getUserId().isEmpty()) // 检查userId不为空
|
||||
.filter(u -> u.getAuthorities() != null && !u.getAuthorities().isEmpty()) // 检查authorities不为空
|
||||
.isPresent(); // 如果上述条件都满足,则返回true,否则返回false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.utils;
|
||||
|
||||
/**
|
||||
* OAuth2CodeUtil
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public class OAuth2CodeUtil {
|
||||
|
||||
/**
|
||||
* 授权码缓存key
|
||||
*/
|
||||
public static final String AUTHORIZATION_CODE_KEY = "blade:auth::code:";
|
||||
|
||||
/**
|
||||
* code key格式
|
||||
*
|
||||
* @param code code
|
||||
* @return key
|
||||
*/
|
||||
public static String codeKey(String code) {
|
||||
return AUTHORIZATION_CODE_KEY + code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.utils;
|
||||
|
||||
import org.springblade.core.oauth2.exception.*;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.springblade.core.oauth2.exception.OAuth2ErrorMessage.INVALID_ERROR_CODE;
|
||||
|
||||
/**
|
||||
* OAuth2ExceptionUtil
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public class OAuth2ExceptionUtil {
|
||||
private static final Map<ExceptionCode, Supplier<OAuth2Exception>> OAUTH2_EXCEPTION = new ConcurrentHashMap<>(16);
|
||||
|
||||
static {
|
||||
// 初始化异常映射
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.INVALID_REQUEST, () -> new OAuth2Exception(ExceptionCode.INVALID_REQUEST, ExceptionCode.INVALID_REQUEST.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.USER_NOT_FOUND, () -> new UsernameNotFoundException(ExceptionCode.USER_NOT_FOUND.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.USER_TENANT_NOT_FOUND, () -> new UserInvalidException(ExceptionCode.USER_TENANT_NOT_FOUND.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.USER_TOO_MANY_FAILS, () -> new UserInvalidException(ExceptionCode.USER_TOO_MANY_FAILS.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.INVALID_USER, () -> new UserInvalidException(ExceptionCode.INVALID_USER.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.UNAUTHORIZED_USER, () -> new UserUnauthorizedException(ExceptionCode.UNAUTHORIZED_USER.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.UNAUTHORIZED_USER_TENANT, () -> new UserUnauthorizedException(ExceptionCode.UNAUTHORIZED_USER_TENANT.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.INVALID_REFRESH_TOKEN, () -> new GranterInvalidException(ExceptionCode.INVALID_REFRESH_TOKEN.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.CLIENT_NOT_FOUND, () -> new ClientNotFoundException(ExceptionCode.CLIENT_NOT_FOUND.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.INVALID_CLIENT, () -> new ClientInvalidException(ExceptionCode.INVALID_CLIENT.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.INVALID_CLIENT_REDIRECT_URI, () -> new ClientInvalidException(ExceptionCode.INVALID_CLIENT_REDIRECT_URI.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.UNAUTHORIZED_CLIENT, () -> new ClientUnauthorizedException(ExceptionCode.UNAUTHORIZED_CLIENT.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.UNSUPPORTED_GRANT_TYPE, () -> new OAuth2Exception(ExceptionCode.UNSUPPORTED_GRANT_TYPE, ExceptionCode.UNSUPPORTED_GRANT_TYPE.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.INVALID_GRANTER, () -> new GranterInvalidException(ExceptionCode.INVALID_GRANTER.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.INVALID_SCOPE, () -> new OAuth2Exception(ExceptionCode.INVALID_SCOPE, ExceptionCode.INVALID_SCOPE.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.SERVER_ERROR, () -> new OAuth2Exception(ExceptionCode.SERVER_ERROR, ExceptionCode.SERVER_ERROR.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.ACCESS_DENIED, () -> new OAuth2Exception(ExceptionCode.ACCESS_DENIED, ExceptionCode.ACCESS_DENIED.getMessage())
|
||||
);
|
||||
OAUTH2_EXCEPTION.put(
|
||||
ExceptionCode.TEMPORARILY_UNAVAILABLE, () -> new OAuth2Exception(ExceptionCode.TEMPORARILY_UNAVAILABLE, ExceptionCode.TEMPORARILY_UNAVAILABLE.getMessage())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据错误代码抛出异常
|
||||
*
|
||||
* @param code 错误代码
|
||||
*/
|
||||
public static void throwFromCode(int code) {
|
||||
Supplier<OAuth2Exception> exceptionSupplier = OAUTH2_EXCEPTION.get(ExceptionCode.of(code));
|
||||
if (exceptionSupplier != null) {
|
||||
throw exceptionSupplier.get();
|
||||
} else {
|
||||
throw new IllegalArgumentException(String.format(INVALID_ERROR_CODE, code));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
* <p>
|
||||
* Use of this software is governed by the Commercial License Agreement
|
||||
* obtained after purchasing a license from BladeX.
|
||||
* <p>
|
||||
* 1. This software is for development use only under a valid license
|
||||
* from BladeX.
|
||||
* <p>
|
||||
* 2. Redistribution of this software's source code to any third party
|
||||
* without a commercial license is strictly prohibited.
|
||||
* <p>
|
||||
* 3. Licensees may copyright their own code but cannot use segments
|
||||
* from this software for such purposes. Copyright of this software
|
||||
* remains with BladeX.
|
||||
* <p>
|
||||
* Using this software signifies agreement to this License, and the software
|
||||
* must not be used for illegal purposes.
|
||||
* <p>
|
||||
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
|
||||
* not liable for any claims arising from secondary or illegal development.
|
||||
* <p>
|
||||
* Author: Chill Zhuang (bladejava@qq.com)
|
||||
*/
|
||||
package org.springblade.core.oauth2.utils;
|
||||
|
||||
import org.springblade.core.oauth2.service.OAuth2Client;
|
||||
import org.springblade.core.oauth2.service.OAuth2User;
|
||||
import org.springblade.core.secure.TokenInfo;
|
||||
import org.springblade.core.secure.utils.SecureUtil;
|
||||
import org.springblade.core.tool.support.Kv;
|
||||
|
||||
import static org.springblade.core.launch.constant.TokenConstant.*;
|
||||
|
||||
/**
|
||||
* OAuth2Util
|
||||
*
|
||||
* @author BladeX
|
||||
*/
|
||||
public class OAuth2Util extends SecureUtil {
|
||||
|
||||
/**
|
||||
* 创建accessToken
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return accessToken
|
||||
*/
|
||||
public static TokenInfo createAccessToken(OAuth2User user) {
|
||||
Kv kv = Kv.create().set(TOKEN_TYPE, ACCESS_TOKEN)
|
||||
.set(CLIENT_ID, user.getClient().getClientId())
|
||||
.set(TENANT_ID, user.getTenantId())
|
||||
.set(USER_ID, user.getUserId())
|
||||
.set(DEPT_ID, user.getDeptId())
|
||||
.set(POST_ID, user.getPostId())
|
||||
.set(ROLE_ID, user.getRoleId())
|
||||
.set(OAUTH_ID, user.getOauthId())
|
||||
.set(ACCOUNT, user.getAccount())
|
||||
.set(USER_NAME, user.getAccount())
|
||||
.set(NICK_NAME, user.getName())
|
||||
.set(REAL_NAME, user.getRealName())
|
||||
.set(ROLE_NAME, user.getRoleName())
|
||||
.set(DETAIL, user.getDetail());
|
||||
return createToken(kv, user.getClient().getAccessTokenValidity());
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建refreshToken
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return refreshToken
|
||||
*/
|
||||
public static TokenInfo createRefreshToken(OAuth2User user) {
|
||||
Kv kv = Kv.create().set(TOKEN_TYPE, REFRESH_TOKEN)
|
||||
.set(USER_ID, user.getUserId())
|
||||
.set(DEPT_ID, user.getDeptId())
|
||||
.set(ROLE_ID, user.getRoleId());
|
||||
return createToken(kv, user.getClient().getRefreshTokenValidity());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 创建clientAccessToken
|
||||
*
|
||||
* @param client 客户端信息
|
||||
* @return clientToken
|
||||
*/
|
||||
public static TokenInfo createClientAccessToken(OAuth2Client client) {
|
||||
Kv kv = Kv.create().set(TOKEN_TYPE, CLIENT_ACCESS_TOKEN)
|
||||
.set(CLIENT_ID, client.getClientId());
|
||||
return createToken(kv, client.getAccessTokenValidity());
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建implicitAccessToken
|
||||
*
|
||||
* @param user 用户信息
|
||||
* @return implicitAccessToken
|
||||
*/
|
||||
public static TokenInfo createImplicitAccessToken(OAuth2User user) {
|
||||
Kv kv = Kv.create().set(TOKEN_TYPE, IMPLICIT_ACCESS_TOKEN)
|
||||
.set(ACCOUNT, user.getAccount());
|
||||
return createToken(kv);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
6
blade-core-oauth2/src/main/resources/static/css/bootstrap.min.css
vendored
Normal file
6
blade-core-oauth2/src/main/resources/static/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1887
blade-core-oauth2/src/main/resources/static/css/iofrm-style.css
Normal file
1887
blade-core-oauth2/src/main/resources/static/css/iofrm-style.css
Normal file
File diff suppressed because it is too large
Load Diff
571
blade-core-oauth2/src/main/resources/static/css/iofrm-theme.css
Normal file
571
blade-core-oauth2/src/main/resources/static/css/iofrm-theme.css
Normal file
@@ -0,0 +1,571 @@
|
||||
/*------------------------------------------------------------------
|
||||
* Theme Name: iofrm - form templates
|
||||
* Theme URI: http://www.brandio.io/envato/iofrm
|
||||
* Author: Brandio
|
||||
* Author URI: http://www.brandio.io/
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
-------------------------------------------------------------------*/
|
||||
|
||||
body {
|
||||
background-color: #152733;
|
||||
}
|
||||
|
||||
.form-body {
|
||||
background-color: #152733;
|
||||
}
|
||||
|
||||
.website-logo {
|
||||
display: none;
|
||||
top: 50px;
|
||||
left: 50px;
|
||||
right: initial;
|
||||
bottom: initial;
|
||||
}
|
||||
|
||||
.website-logo img {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.website-logo .logo {
|
||||
background-image: url("../images/logo-light.svg");
|
||||
}
|
||||
|
||||
.website-logo .logo img {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.website-logo-inside img {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.website-logo-inside .logo {
|
||||
background-image: url("../images/logo-light.svg");
|
||||
}
|
||||
|
||||
.website-logo-inside .logo img {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.img-holder {
|
||||
width: 0;
|
||||
background-color: #5CBAFF;
|
||||
}
|
||||
|
||||
.img-holder .info-holder h3 {
|
||||
color: #fff;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.img-holder .info-holder h3 span {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.img-holder .info-holder h2 {
|
||||
color: #fff;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.img-holder .info-holder h2 span {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.img-holder .info-holder p {
|
||||
color: #fff;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.img-holder .bg {
|
||||
opacity: 0.23;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.form-holder {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.form-holder .form-content ::-webkit-input-placeholder {
|
||||
color: #8D8D8D !important;
|
||||
}
|
||||
|
||||
.form-holder .form-content :-moz-placeholder {
|
||||
color: #8D8D8D !important;
|
||||
}
|
||||
|
||||
.form-holder .form-content ::-moz-placeholder {
|
||||
color: #8D8D8D !important;
|
||||
}
|
||||
|
||||
.form-holder .form-content :-ms-input-placeholder {
|
||||
color: #8D8D8D !important;
|
||||
}
|
||||
|
||||
.form-content {
|
||||
background-color: #152733;
|
||||
}
|
||||
|
||||
.form-content .form-group {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.form-content .form-items {
|
||||
max-width: 380px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-content .form-icon {
|
||||
margin-top: calc(-42px - 35px);
|
||||
}
|
||||
|
||||
.form-content .form-icon .icon-holder {
|
||||
background-color: #4A77F7;
|
||||
}
|
||||
|
||||
.form-content h1 {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-content h2 {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-content h3 {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-content p {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-content label {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-content .page-links a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.form-content .page-links a:after {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.form-content .page-links a.active:after {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.form-content .page-links a:hover:after, .form-content .page-links a:focus:after {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.form-content input, .form-content .dropdown-toggle.btn-default {
|
||||
border: 0;
|
||||
background-color: #fff;
|
||||
color: #8D8D8D;
|
||||
}
|
||||
|
||||
.form-content input:hover, .form-content input:focus, .form-content .dropdown-toggle.btn-default:hover, .form-content .dropdown-toggle.btn-default:focus {
|
||||
border: 0;
|
||||
background-color: #ebeff8;
|
||||
color: #8D8D8D;
|
||||
}
|
||||
|
||||
.form-content textarea {
|
||||
border: 0;
|
||||
background-color: #fff;
|
||||
color: #8D8D8D;
|
||||
}
|
||||
|
||||
.form-content textarea:hover, .form-content textarea:focus {
|
||||
border: 0;
|
||||
background-color: #ebeff8;
|
||||
color: #8D8D8D;
|
||||
}
|
||||
|
||||
.form-content .custom-file-label {
|
||||
border: 0;
|
||||
background-color: #fff;
|
||||
color: #8D8D8D;
|
||||
}
|
||||
|
||||
.form-content .custom-file-label:after {
|
||||
color: #0093FF;
|
||||
}
|
||||
|
||||
.form-content .custom-file:hover .custom-file-label, .form-content .custom-file:focus .custom-file-label {
|
||||
border: 0;
|
||||
background-color: #ebeff8;
|
||||
color: #8D8D8D;
|
||||
}
|
||||
|
||||
.form-content input[type=checkbox]:not(:checked) + label, .form-content input[type=checkbox]:checked + label, .form-content input[type=radio]:not(:checked) + label, .form-content input[type=radio]:checked + label {
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.form-content input[type=checkbox]:checked + label, .form-content input[type=radio]:checked + label {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.form-content input[type=checkbox]:checked + label:before, .form-content input[type=radio]:checked + label:before {
|
||||
background: #fff;
|
||||
border: 0px solid #fff;
|
||||
}
|
||||
|
||||
.form-content input[type=checkbox]:not(:checked) + label:before, .form-content input[type=radio]:not(:checked) + label:before {
|
||||
background: transparent;
|
||||
border: 2px solid #fff;
|
||||
}
|
||||
|
||||
.form-content input[type=checkbox]:not(:checked) + label:after, .form-content input[type=checkbox]:checked + label:after {
|
||||
color: #152733;
|
||||
}
|
||||
|
||||
.form-content input[type=radio]:not(:checked) + label:after, .form-content input[type=radio]:checked + label:after {
|
||||
background-color: #152733;
|
||||
}
|
||||
|
||||
.form-content .custom-options input[type=checkbox]:not(:checked) + label, .form-content .custom-options input[type=checkbox]:checked + label, .form-content .custom-options input[type=radio]:not(:checked) + label, .form-content .custom-options input[type=radio]:checked + label {
|
||||
color: #606060;
|
||||
background-color: #F7F7F7;
|
||||
}
|
||||
|
||||
.form-content .custom-options input[type=checkbox]:checked + label, .form-content .custom-options input[type=radio]:checked + label {
|
||||
color: #fff;
|
||||
background-color: #1592E6;
|
||||
-webkit-box-shadow: 0 3px 8px rgba(0, 0, 0, 0.16);
|
||||
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
|
||||
.form-content .form-button .lbtn {
|
||||
margin-top: 10px;
|
||||
background-color: #cb3444;
|
||||
color: #fff;
|
||||
-webkit-box-shadow: 0 0 0 rgba(0, 0, 0, 0.16);
|
||||
box-shadow: 0 0 0 rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
|
||||
.form-content .form-button .lbtn:hover, .form-content .form-button .lbtn:focus {
|
||||
background-color: #cb3444;
|
||||
color: #fff;
|
||||
-webkit-box-shadow: 0 5px 6px rgba(0, 0, 0, 0.16);
|
||||
box-shadow: 0 5px 6px rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
|
||||
.form-content .form-button .ibtn {
|
||||
background-color: #1592E6;
|
||||
color: #fff;
|
||||
-webkit-box-shadow: 0 0 0 rgba(0, 0, 0, 0.16);
|
||||
box-shadow: 0 0 0 rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
|
||||
.form-content .form-button .ibtn:hover, .form-content .form-button .ibtn:focus {
|
||||
background-color: #1592E6;
|
||||
color: #fff;
|
||||
-webkit-box-shadow: 0 5px 6px rgba(0, 0, 0, 0.16);
|
||||
box-shadow: 0 5px 6px rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
|
||||
.form-content .form-button a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.form-content .other-links span {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.form-content .other-links a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.form-content .form-sent .tick-holder .tick-icon {
|
||||
background-color: rgba(14, 30, 41, 0);
|
||||
}
|
||||
|
||||
.form-content .form-sent .tick-holder .tick-icon:before {
|
||||
background-color: #8CCB57;
|
||||
}
|
||||
|
||||
.form-content .form-sent .tick-holder .tick-icon:after {
|
||||
background-color: #8CCB57;
|
||||
}
|
||||
|
||||
.form-content .form-sent h3 {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.form-content .form-sent p {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.form-content .form-sent .info-holder {
|
||||
color: #fff;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.form-content .form-sent .info-holder span {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.form-content .form-sent .info-holder a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@keyframes tick-anime3 {
|
||||
0% {
|
||||
background-color: rgba(14, 30, 41, 0);
|
||||
-webkit-transform: rotate(35deg) scale(2);
|
||||
-moz-transform: rotate(35deg) scale(2);
|
||||
-ms-transform: rotate(35deg) scale(2);
|
||||
transform: rotate(35deg) scale(2);
|
||||
}
|
||||
|
||||
100% {
|
||||
background-color: #0E1E29;
|
||||
-webkit-transform: rotate(45deg) scale(1);
|
||||
-moz-transform: rotate(45deg) scale(1);
|
||||
-ms-transform: rotate(45deg) scale(1);
|
||||
transform: rotate(45deg) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.alert {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.alert.alert-primary {
|
||||
background-color: rgba(226, 240, 255, 0);
|
||||
border-color: #3a86d6;
|
||||
}
|
||||
|
||||
.alert.alert-primary hr {
|
||||
border-top-color: #3a86d6;
|
||||
}
|
||||
|
||||
.alert.alert-secondary {
|
||||
background-color: rgba(240, 240, 240, 0);
|
||||
border-color: #8e9396;
|
||||
}
|
||||
|
||||
.alert.alert-secondary hr {
|
||||
border-top-color: #8e9396;
|
||||
}
|
||||
|
||||
.alert.alert-success {
|
||||
background-color: rgba(247, 255, 240, 0);
|
||||
border-color: #8CCB57;
|
||||
}
|
||||
|
||||
.alert.alert-success hr {
|
||||
border-top-color: #8CCB57;
|
||||
}
|
||||
|
||||
.alert.alert-danger {
|
||||
background-color: rgba(255, 250, 250, 0);
|
||||
border-color: #F55050;
|
||||
}
|
||||
|
||||
.alert.alert-danger hr {
|
||||
border-top-color: #F55050;
|
||||
}
|
||||
|
||||
.alert.alert-warning {
|
||||
background-color: rgba(255, 248, 225, 0);
|
||||
border-color: #f1cb4b;
|
||||
}
|
||||
|
||||
.alert.alert-warning hr {
|
||||
border-top-color: #f1cb4b;
|
||||
}
|
||||
|
||||
.alert.alert-info {
|
||||
background-color: rgba(220, 237, 241, 0);
|
||||
border-color: #42bfdb;
|
||||
}
|
||||
|
||||
.alert.alert-info hr {
|
||||
border-top-color: #42bfdb;
|
||||
}
|
||||
|
||||
.alert.alert-light {
|
||||
background-color: rgba(254, 254, 254, 0);
|
||||
border-color: #a7a4a4;
|
||||
}
|
||||
|
||||
.alert.alert-light hr {
|
||||
border-top-color: #a7a4a4;
|
||||
}
|
||||
|
||||
.alert.alert-dark {
|
||||
background-color: rgba(214, 216, 217, 0);
|
||||
border-color: #525557;
|
||||
}
|
||||
|
||||
.alert.alert-dark hr {
|
||||
border-top-color: #525557;
|
||||
}
|
||||
|
||||
.alert.with-icon.alert-primary:before {
|
||||
color: #3a86d6;
|
||||
}
|
||||
|
||||
.alert.with-icon.alert-secondary:before {
|
||||
color: #8e9396;
|
||||
}
|
||||
|
||||
.alert.with-icon.alert-success:before {
|
||||
color: #8CCB57;
|
||||
}
|
||||
|
||||
.alert.with-icon.alert-danger:before {
|
||||
color: #F55050;
|
||||
}
|
||||
|
||||
.alert.with-icon.alert-warning:before {
|
||||
color: #f1cb4b;
|
||||
}
|
||||
|
||||
.alert.with-icon.alert-info:before {
|
||||
color: #42bfdb;
|
||||
}
|
||||
|
||||
.alert.with-icon.alert-light:before {
|
||||
color: #a7a4a4;
|
||||
}
|
||||
|
||||
.alert.with-icon.alert-dark:before {
|
||||
color: #525557;
|
||||
}
|
||||
|
||||
.alert a, .alert a.alert-link {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.alert .close {
|
||||
color: #727272;
|
||||
}
|
||||
|
||||
.alert .close span {
|
||||
color: #727272;
|
||||
}
|
||||
|
||||
.form-subtitle {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.rad-with-details .more-info {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.form-body.without-side h3 {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.form-body.without-side p {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.form-body.without-side label {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.form-body.without-side .img-holder .info-holder img {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.form-body.without-side .form-content .form-items {
|
||||
padding: 35px 30px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.form-body.without-side .form-content .form-items .other-links .text {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.form-body.without-side .form-content .form-items .other-links a {
|
||||
color: #000;
|
||||
background-color: #F7F7F7;
|
||||
}
|
||||
|
||||
.form-body.without-side .form-content .page-links a {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.form-body.without-side .form-content .page-links a:after {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.form-body.without-side .form-content .page-links a.active:after {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.form-body.without-side .form-content .page-links a:hover:after, .form-body.without-side .form-content .page-links a:focus:after {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.form-body.without-side .form-content input, .form-body.without-side .form-content .dropdown-toggle.btn-default {
|
||||
border: 0;
|
||||
background-color: #fff;
|
||||
color: #8D8D8D;
|
||||
}
|
||||
|
||||
.form-body.without-side .form-content input:hover, .form-body.without-side .form-content input:focus, .form-body.without-side .form-content .dropdown-toggle.btn-default:hover, .form-body.without-side .form-content .dropdown-toggle.btn-default:focus {
|
||||
border: 0;
|
||||
background-color: #fff;
|
||||
color: #8D8D8D;
|
||||
}
|
||||
|
||||
.form-body.without-side .form-content .form-button .lbtn {
|
||||
background-color: #cb3444;
|
||||
color: #fff;
|
||||
-webkit-box-shadow: 0 0 0 rgba(0, 0, 0, 0.16);
|
||||
box-shadow: 0 0 0 rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
|
||||
.form-body.without-side .form-content .form-button .lbtn:hover, .form-body.without-side .form-content .form-button .lbtn:focus {
|
||||
-webkit-box-shadow: 0 5px 6px rgba(0, 0, 0, 0.16);
|
||||
box-shadow: 0 5px 6px rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
|
||||
.form-body.without-side .form-content .form-button .ibtn {
|
||||
background-color: #1592E6;
|
||||
color: #fff;
|
||||
-webkit-box-shadow: 0 0 0 rgba(0, 0, 0, 0.16);
|
||||
box-shadow: 0 0 0 rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
|
||||
.form-body.without-side .form-content .form-button .ibtn:hover, .form-body.without-side .form-content .form-button .ibtn:focus {
|
||||
-webkit-box-shadow: 0 5px 6px rgba(0, 0, 0, 0.16);
|
||||
box-shadow: 0 5px 6px rgba(0, 0, 0, 0.16);
|
||||
}
|
||||
|
||||
.form-body.without-side .form-content .form-button a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* -----------------------------------
|
||||
2 - Responsive Styles
|
||||
------------------------------------*/
|
||||
@media (max-width: 992px) {
|
||||
.form-holder {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.website-logo {
|
||||
top: 50px;
|
||||
left: 50px;
|
||||
right: initial;
|
||||
bottom: initial;
|
||||
}
|
||||
|
||||
.website-logo .logo {
|
||||
background-image: url("../images/logo-light.svg");
|
||||
}
|
||||
|
||||
.form-body.without-side .website-logo .logo {
|
||||
background-image: url("../images/logo-light.svg");
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 123 KiB |
6
blade-core-oauth2/src/main/resources/static/js/bootstrap.min.js
vendored
Normal file
6
blade-core-oauth2/src/main/resources/static/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
blade-core-oauth2/src/main/resources/static/js/jquery.min.js
vendored
Normal file
2
blade-core-oauth2/src/main/resources/static/js/jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
683
blade-core-oauth2/src/main/resources/static/js/md5.js
Normal file
683
blade-core-oauth2/src/main/resources/static/js/md5.js
Normal file
@@ -0,0 +1,683 @@
|
||||
/**
|
||||
* [js-md5]{@link https://github.com/emn178/js-md5}
|
||||
*
|
||||
* @namespace md5
|
||||
* @version 0.7.3
|
||||
* @author Chen, Yi-Cyuan [emn178@gmail.com]
|
||||
* @copyright Chen, Yi-Cyuan 2014-2017
|
||||
* @license MIT
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var ERROR = 'input is invalid type';
|
||||
var WINDOW = typeof window === 'object';
|
||||
var root = WINDOW ? window : {};
|
||||
if (root.JS_MD5_NO_WINDOW) {
|
||||
WINDOW = false;
|
||||
}
|
||||
var WEB_WORKER = !WINDOW && typeof self === 'object';
|
||||
var NODE_JS = !root.JS_MD5_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
|
||||
if (NODE_JS) {
|
||||
root = global;
|
||||
} else if (WEB_WORKER) {
|
||||
root = self;
|
||||
}
|
||||
var COMMON_JS = !root.JS_MD5_NO_COMMON_JS && typeof module === 'object' && module.exports;
|
||||
var AMD = typeof define === 'function' && define.amd;
|
||||
var ARRAY_BUFFER = !root.JS_MD5_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';
|
||||
var HEX_CHARS = '0123456789abcdef'.split('');
|
||||
var EXTRA = [128, 32768, 8388608, -2147483648];
|
||||
var SHIFT = [0, 8, 16, 24];
|
||||
var OUTPUT_TYPES = ['hex', 'array', 'digest', 'buffer', 'arrayBuffer', 'base64'];
|
||||
var BASE64_ENCODE_CHAR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');
|
||||
|
||||
var blocks = [], buffer8;
|
||||
if (ARRAY_BUFFER) {
|
||||
var buffer = new ArrayBuffer(68);
|
||||
buffer8 = new Uint8Array(buffer);
|
||||
blocks = new Uint32Array(buffer);
|
||||
}
|
||||
|
||||
if (root.JS_MD5_NO_NODE_JS || !Array.isArray) {
|
||||
Array.isArray = function (obj) {
|
||||
return Object.prototype.toString.call(obj) === '[object Array]';
|
||||
};
|
||||
}
|
||||
|
||||
if (ARRAY_BUFFER && (root.JS_MD5_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView)) {
|
||||
ArrayBuffer.isView = function (obj) {
|
||||
return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @method hex
|
||||
* @memberof md5
|
||||
* @description Output hash as hex string
|
||||
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
|
||||
* @returns {String} Hex string
|
||||
* @example
|
||||
* md5.hex('The quick brown fox jumps over the lazy dog');
|
||||
* // equal to
|
||||
* md5('The quick brown fox jumps over the lazy dog');
|
||||
*/
|
||||
/**
|
||||
* @method digest
|
||||
* @memberof md5
|
||||
* @description Output hash as bytes array
|
||||
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
|
||||
* @returns {Array} Bytes array
|
||||
* @example
|
||||
* md5.digest('The quick brown fox jumps over the lazy dog');
|
||||
*/
|
||||
/**
|
||||
* @method array
|
||||
* @memberof md5
|
||||
* @description Output hash as bytes array
|
||||
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
|
||||
* @returns {Array} Bytes array
|
||||
* @example
|
||||
* md5.array('The quick brown fox jumps over the lazy dog');
|
||||
*/
|
||||
/**
|
||||
* @method arrayBuffer
|
||||
* @memberof md5
|
||||
* @description Output hash as ArrayBuffer
|
||||
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
|
||||
* @returns {ArrayBuffer} ArrayBuffer
|
||||
* @example
|
||||
* md5.arrayBuffer('The quick brown fox jumps over the lazy dog');
|
||||
*/
|
||||
/**
|
||||
* @method buffer
|
||||
* @deprecated This maybe confuse with Buffer in node.js. Please use arrayBuffer instead.
|
||||
* @memberof md5
|
||||
* @description Output hash as ArrayBuffer
|
||||
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
|
||||
* @returns {ArrayBuffer} ArrayBuffer
|
||||
* @example
|
||||
* md5.buffer('The quick brown fox jumps over the lazy dog');
|
||||
*/
|
||||
/**
|
||||
* @method base64
|
||||
* @memberof md5
|
||||
* @description Output hash as base64 string
|
||||
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
|
||||
* @returns {String} base64 string
|
||||
* @example
|
||||
* md5.base64('The quick brown fox jumps over the lazy dog');
|
||||
*/
|
||||
var createOutputMethod = function (outputType) {
|
||||
return function (message) {
|
||||
return new Md5(true).update(message)[outputType]();
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @method create
|
||||
* @memberof md5
|
||||
* @description Create Md5 object
|
||||
* @returns {Md5} Md5 object.
|
||||
* @example
|
||||
* var hash = md5.create();
|
||||
*/
|
||||
/**
|
||||
* @method update
|
||||
* @memberof md5
|
||||
* @description Create and update Md5 object
|
||||
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
|
||||
* @returns {Md5} Md5 object.
|
||||
* @example
|
||||
* var hash = md5.update('The quick brown fox jumps over the lazy dog');
|
||||
* // equal to
|
||||
* var hash = md5.create();
|
||||
* hash.update('The quick brown fox jumps over the lazy dog');
|
||||
*/
|
||||
var createMethod = function () {
|
||||
var method = createOutputMethod('hex');
|
||||
if (NODE_JS) {
|
||||
method = nodeWrap(method);
|
||||
}
|
||||
method.create = function () {
|
||||
return new Md5();
|
||||
};
|
||||
method.update = function (message) {
|
||||
return method.create().update(message);
|
||||
};
|
||||
for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
|
||||
var type = OUTPUT_TYPES[i];
|
||||
method[type] = createOutputMethod(type);
|
||||
}
|
||||
return method;
|
||||
};
|
||||
|
||||
var nodeWrap = function (method) {
|
||||
var crypto = eval("require('crypto')");
|
||||
var Buffer = eval("require('buffer').Buffer");
|
||||
var nodeMethod = function (message) {
|
||||
if (typeof message === 'string') {
|
||||
return crypto.createHash('md5').update(message, 'utf8').digest('hex');
|
||||
} else {
|
||||
if (message === null || message === undefined) {
|
||||
throw ERROR;
|
||||
} else if (message.constructor === ArrayBuffer) {
|
||||
message = new Uint8Array(message);
|
||||
}
|
||||
}
|
||||
if (Array.isArray(message) || ArrayBuffer.isView(message) ||
|
||||
message.constructor === Buffer) {
|
||||
return crypto.createHash('md5').update(new Buffer(message)).digest('hex');
|
||||
} else {
|
||||
return method(message);
|
||||
}
|
||||
};
|
||||
return nodeMethod;
|
||||
};
|
||||
|
||||
/**
|
||||
* Md5 class
|
||||
* @class Md5
|
||||
* @description This is internal class.
|
||||
* @see {@link md5.create}
|
||||
*/
|
||||
function Md5(sharedMemory) {
|
||||
if (sharedMemory) {
|
||||
blocks[0] = blocks[16] = blocks[1] = blocks[2] = blocks[3] =
|
||||
blocks[4] = blocks[5] = blocks[6] = blocks[7] =
|
||||
blocks[8] = blocks[9] = blocks[10] = blocks[11] =
|
||||
blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
|
||||
this.blocks = blocks;
|
||||
this.buffer8 = buffer8;
|
||||
} else {
|
||||
if (ARRAY_BUFFER) {
|
||||
var buffer = new ArrayBuffer(68);
|
||||
this.buffer8 = new Uint8Array(buffer);
|
||||
this.blocks = new Uint32Array(buffer);
|
||||
} else {
|
||||
this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
}
|
||||
}
|
||||
this.h0 = this.h1 = this.h2 = this.h3 = this.start = this.bytes = this.hBytes = 0;
|
||||
this.finalized = this.hashed = false;
|
||||
this.first = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method update
|
||||
* @memberof Md5
|
||||
* @instance
|
||||
* @description Update hash
|
||||
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
|
||||
* @returns {Md5} Md5 object.
|
||||
* @see {@link md5.update}
|
||||
*/
|
||||
Md5.prototype.update = function (message) {
|
||||
if (this.finalized) {
|
||||
return;
|
||||
}
|
||||
|
||||
var notString, type = typeof message;
|
||||
if (type !== 'string') {
|
||||
if (type === 'object') {
|
||||
if (message === null) {
|
||||
throw ERROR;
|
||||
} else if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {
|
||||
message = new Uint8Array(message);
|
||||
} else if (!Array.isArray(message)) {
|
||||
if (!ARRAY_BUFFER || !ArrayBuffer.isView(message)) {
|
||||
throw ERROR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw ERROR;
|
||||
}
|
||||
notString = true;
|
||||
}
|
||||
var code, index = 0, i, length = message.length, blocks = this.blocks;
|
||||
var buffer8 = this.buffer8;
|
||||
|
||||
while (index < length) {
|
||||
if (this.hashed) {
|
||||
this.hashed = false;
|
||||
blocks[0] = blocks[16];
|
||||
blocks[16] = blocks[1] = blocks[2] = blocks[3] =
|
||||
blocks[4] = blocks[5] = blocks[6] = blocks[7] =
|
||||
blocks[8] = blocks[9] = blocks[10] = blocks[11] =
|
||||
blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
|
||||
}
|
||||
|
||||
if (notString) {
|
||||
if (ARRAY_BUFFER) {
|
||||
for (i = this.start; index < length && i < 64; ++index) {
|
||||
buffer8[i++] = message[index];
|
||||
}
|
||||
} else {
|
||||
for (i = this.start; index < length && i < 64; ++index) {
|
||||
blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ARRAY_BUFFER) {
|
||||
for (i = this.start; index < length && i < 64; ++index) {
|
||||
code = message.charCodeAt(index);
|
||||
if (code < 0x80) {
|
||||
buffer8[i++] = code;
|
||||
} else if (code < 0x800) {
|
||||
buffer8[i++] = 0xc0 | (code >> 6);
|
||||
buffer8[i++] = 0x80 | (code & 0x3f);
|
||||
} else if (code < 0xd800 || code >= 0xe000) {
|
||||
buffer8[i++] = 0xe0 | (code >> 12);
|
||||
buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);
|
||||
buffer8[i++] = 0x80 | (code & 0x3f);
|
||||
} else {
|
||||
code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
|
||||
buffer8[i++] = 0xf0 | (code >> 18);
|
||||
buffer8[i++] = 0x80 | ((code >> 12) & 0x3f);
|
||||
buffer8[i++] = 0x80 | ((code >> 6) & 0x3f);
|
||||
buffer8[i++] = 0x80 | (code & 0x3f);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = this.start; index < length && i < 64; ++index) {
|
||||
code = message.charCodeAt(index);
|
||||
if (code < 0x80) {
|
||||
blocks[i >> 2] |= code << SHIFT[i++ & 3];
|
||||
} else if (code < 0x800) {
|
||||
blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
|
||||
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
|
||||
} else if (code < 0xd800 || code >= 0xe000) {
|
||||
blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
|
||||
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
|
||||
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
|
||||
} else {
|
||||
code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
|
||||
blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
|
||||
blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
|
||||
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
|
||||
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.lastByteIndex = i;
|
||||
this.bytes += i - this.start;
|
||||
if (i >= 64) {
|
||||
this.start = i - 64;
|
||||
this.hash();
|
||||
this.hashed = true;
|
||||
} else {
|
||||
this.start = i;
|
||||
}
|
||||
}
|
||||
if (this.bytes > 4294967295) {
|
||||
this.hBytes += this.bytes / 4294967296 << 0;
|
||||
this.bytes = this.bytes % 4294967296;
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
Md5.prototype.finalize = function () {
|
||||
if (this.finalized) {
|
||||
return;
|
||||
}
|
||||
this.finalized = true;
|
||||
var blocks = this.blocks, i = this.lastByteIndex;
|
||||
blocks[i >> 2] |= EXTRA[i & 3];
|
||||
if (i >= 56) {
|
||||
if (!this.hashed) {
|
||||
this.hash();
|
||||
}
|
||||
blocks[0] = blocks[16];
|
||||
blocks[16] = blocks[1] = blocks[2] = blocks[3] =
|
||||
blocks[4] = blocks[5] = blocks[6] = blocks[7] =
|
||||
blocks[8] = blocks[9] = blocks[10] = blocks[11] =
|
||||
blocks[12] = blocks[13] = blocks[14] = blocks[15] = 0;
|
||||
}
|
||||
blocks[14] = this.bytes << 3;
|
||||
blocks[15] = this.hBytes << 3 | this.bytes >>> 29;
|
||||
this.hash();
|
||||
};
|
||||
|
||||
Md5.prototype.hash = function () {
|
||||
var a, b, c, d, bc, da, blocks = this.blocks;
|
||||
|
||||
if (this.first) {
|
||||
a = blocks[0] - 680876937;
|
||||
a = (a << 7 | a >>> 25) - 271733879 << 0;
|
||||
d = (-1732584194 ^ a & 2004318071) + blocks[1] - 117830708;
|
||||
d = (d << 12 | d >>> 20) + a << 0;
|
||||
c = (-271733879 ^ (d & (a ^ -271733879))) + blocks[2] - 1126478375;
|
||||
c = (c << 17 | c >>> 15) + d << 0;
|
||||
b = (a ^ (c & (d ^ a))) + blocks[3] - 1316259209;
|
||||
b = (b << 22 | b >>> 10) + c << 0;
|
||||
} else {
|
||||
a = this.h0;
|
||||
b = this.h1;
|
||||
c = this.h2;
|
||||
d = this.h3;
|
||||
a += (d ^ (b & (c ^ d))) + blocks[0] - 680876936;
|
||||
a = (a << 7 | a >>> 25) + b << 0;
|
||||
d += (c ^ (a & (b ^ c))) + blocks[1] - 389564586;
|
||||
d = (d << 12 | d >>> 20) + a << 0;
|
||||
c += (b ^ (d & (a ^ b))) + blocks[2] + 606105819;
|
||||
c = (c << 17 | c >>> 15) + d << 0;
|
||||
b += (a ^ (c & (d ^ a))) + blocks[3] - 1044525330;
|
||||
b = (b << 22 | b >>> 10) + c << 0;
|
||||
}
|
||||
|
||||
a += (d ^ (b & (c ^ d))) + blocks[4] - 176418897;
|
||||
a = (a << 7 | a >>> 25) + b << 0;
|
||||
d += (c ^ (a & (b ^ c))) + blocks[5] + 1200080426;
|
||||
d = (d << 12 | d >>> 20) + a << 0;
|
||||
c += (b ^ (d & (a ^ b))) + blocks[6] - 1473231341;
|
||||
c = (c << 17 | c >>> 15) + d << 0;
|
||||
b += (a ^ (c & (d ^ a))) + blocks[7] - 45705983;
|
||||
b = (b << 22 | b >>> 10) + c << 0;
|
||||
a += (d ^ (b & (c ^ d))) + blocks[8] + 1770035416;
|
||||
a = (a << 7 | a >>> 25) + b << 0;
|
||||
d += (c ^ (a & (b ^ c))) + blocks[9] - 1958414417;
|
||||
d = (d << 12 | d >>> 20) + a << 0;
|
||||
c += (b ^ (d & (a ^ b))) + blocks[10] - 42063;
|
||||
c = (c << 17 | c >>> 15) + d << 0;
|
||||
b += (a ^ (c & (d ^ a))) + blocks[11] - 1990404162;
|
||||
b = (b << 22 | b >>> 10) + c << 0;
|
||||
a += (d ^ (b & (c ^ d))) + blocks[12] + 1804603682;
|
||||
a = (a << 7 | a >>> 25) + b << 0;
|
||||
d += (c ^ (a & (b ^ c))) + blocks[13] - 40341101;
|
||||
d = (d << 12 | d >>> 20) + a << 0;
|
||||
c += (b ^ (d & (a ^ b))) + blocks[14] - 1502002290;
|
||||
c = (c << 17 | c >>> 15) + d << 0;
|
||||
b += (a ^ (c & (d ^ a))) + blocks[15] + 1236535329;
|
||||
b = (b << 22 | b >>> 10) + c << 0;
|
||||
a += (c ^ (d & (b ^ c))) + blocks[1] - 165796510;
|
||||
a = (a << 5 | a >>> 27) + b << 0;
|
||||
d += (b ^ (c & (a ^ b))) + blocks[6] - 1069501632;
|
||||
d = (d << 9 | d >>> 23) + a << 0;
|
||||
c += (a ^ (b & (d ^ a))) + blocks[11] + 643717713;
|
||||
c = (c << 14 | c >>> 18) + d << 0;
|
||||
b += (d ^ (a & (c ^ d))) + blocks[0] - 373897302;
|
||||
b = (b << 20 | b >>> 12) + c << 0;
|
||||
a += (c ^ (d & (b ^ c))) + blocks[5] - 701558691;
|
||||
a = (a << 5 | a >>> 27) + b << 0;
|
||||
d += (b ^ (c & (a ^ b))) + blocks[10] + 38016083;
|
||||
d = (d << 9 | d >>> 23) + a << 0;
|
||||
c += (a ^ (b & (d ^ a))) + blocks[15] - 660478335;
|
||||
c = (c << 14 | c >>> 18) + d << 0;
|
||||
b += (d ^ (a & (c ^ d))) + blocks[4] - 405537848;
|
||||
b = (b << 20 | b >>> 12) + c << 0;
|
||||
a += (c ^ (d & (b ^ c))) + blocks[9] + 568446438;
|
||||
a = (a << 5 | a >>> 27) + b << 0;
|
||||
d += (b ^ (c & (a ^ b))) + blocks[14] - 1019803690;
|
||||
d = (d << 9 | d >>> 23) + a << 0;
|
||||
c += (a ^ (b & (d ^ a))) + blocks[3] - 187363961;
|
||||
c = (c << 14 | c >>> 18) + d << 0;
|
||||
b += (d ^ (a & (c ^ d))) + blocks[8] + 1163531501;
|
||||
b = (b << 20 | b >>> 12) + c << 0;
|
||||
a += (c ^ (d & (b ^ c))) + blocks[13] - 1444681467;
|
||||
a = (a << 5 | a >>> 27) + b << 0;
|
||||
d += (b ^ (c & (a ^ b))) + blocks[2] - 51403784;
|
||||
d = (d << 9 | d >>> 23) + a << 0;
|
||||
c += (a ^ (b & (d ^ a))) + blocks[7] + 1735328473;
|
||||
c = (c << 14 | c >>> 18) + d << 0;
|
||||
b += (d ^ (a & (c ^ d))) + blocks[12] - 1926607734;
|
||||
b = (b << 20 | b >>> 12) + c << 0;
|
||||
bc = b ^ c;
|
||||
a += (bc ^ d) + blocks[5] - 378558;
|
||||
a = (a << 4 | a >>> 28) + b << 0;
|
||||
d += (bc ^ a) + blocks[8] - 2022574463;
|
||||
d = (d << 11 | d >>> 21) + a << 0;
|
||||
da = d ^ a;
|
||||
c += (da ^ b) + blocks[11] + 1839030562;
|
||||
c = (c << 16 | c >>> 16) + d << 0;
|
||||
b += (da ^ c) + blocks[14] - 35309556;
|
||||
b = (b << 23 | b >>> 9) + c << 0;
|
||||
bc = b ^ c;
|
||||
a += (bc ^ d) + blocks[1] - 1530992060;
|
||||
a = (a << 4 | a >>> 28) + b << 0;
|
||||
d += (bc ^ a) + blocks[4] + 1272893353;
|
||||
d = (d << 11 | d >>> 21) + a << 0;
|
||||
da = d ^ a;
|
||||
c += (da ^ b) + blocks[7] - 155497632;
|
||||
c = (c << 16 | c >>> 16) + d << 0;
|
||||
b += (da ^ c) + blocks[10] - 1094730640;
|
||||
b = (b << 23 | b >>> 9) + c << 0;
|
||||
bc = b ^ c;
|
||||
a += (bc ^ d) + blocks[13] + 681279174;
|
||||
a = (a << 4 | a >>> 28) + b << 0;
|
||||
d += (bc ^ a) + blocks[0] - 358537222;
|
||||
d = (d << 11 | d >>> 21) + a << 0;
|
||||
da = d ^ a;
|
||||
c += (da ^ b) + blocks[3] - 722521979;
|
||||
c = (c << 16 | c >>> 16) + d << 0;
|
||||
b += (da ^ c) + blocks[6] + 76029189;
|
||||
b = (b << 23 | b >>> 9) + c << 0;
|
||||
bc = b ^ c;
|
||||
a += (bc ^ d) + blocks[9] - 640364487;
|
||||
a = (a << 4 | a >>> 28) + b << 0;
|
||||
d += (bc ^ a) + blocks[12] - 421815835;
|
||||
d = (d << 11 | d >>> 21) + a << 0;
|
||||
da = d ^ a;
|
||||
c += (da ^ b) + blocks[15] + 530742520;
|
||||
c = (c << 16 | c >>> 16) + d << 0;
|
||||
b += (da ^ c) + blocks[2] - 995338651;
|
||||
b = (b << 23 | b >>> 9) + c << 0;
|
||||
a += (c ^ (b | ~d)) + blocks[0] - 198630844;
|
||||
a = (a << 6 | a >>> 26) + b << 0;
|
||||
d += (b ^ (a | ~c)) + blocks[7] + 1126891415;
|
||||
d = (d << 10 | d >>> 22) + a << 0;
|
||||
c += (a ^ (d | ~b)) + blocks[14] - 1416354905;
|
||||
c = (c << 15 | c >>> 17) + d << 0;
|
||||
b += (d ^ (c | ~a)) + blocks[5] - 57434055;
|
||||
b = (b << 21 | b >>> 11) + c << 0;
|
||||
a += (c ^ (b | ~d)) + blocks[12] + 1700485571;
|
||||
a = (a << 6 | a >>> 26) + b << 0;
|
||||
d += (b ^ (a | ~c)) + blocks[3] - 1894986606;
|
||||
d = (d << 10 | d >>> 22) + a << 0;
|
||||
c += (a ^ (d | ~b)) + blocks[10] - 1051523;
|
||||
c = (c << 15 | c >>> 17) + d << 0;
|
||||
b += (d ^ (c | ~a)) + blocks[1] - 2054922799;
|
||||
b = (b << 21 | b >>> 11) + c << 0;
|
||||
a += (c ^ (b | ~d)) + blocks[8] + 1873313359;
|
||||
a = (a << 6 | a >>> 26) + b << 0;
|
||||
d += (b ^ (a | ~c)) + blocks[15] - 30611744;
|
||||
d = (d << 10 | d >>> 22) + a << 0;
|
||||
c += (a ^ (d | ~b)) + blocks[6] - 1560198380;
|
||||
c = (c << 15 | c >>> 17) + d << 0;
|
||||
b += (d ^ (c | ~a)) + blocks[13] + 1309151649;
|
||||
b = (b << 21 | b >>> 11) + c << 0;
|
||||
a += (c ^ (b | ~d)) + blocks[4] - 145523070;
|
||||
a = (a << 6 | a >>> 26) + b << 0;
|
||||
d += (b ^ (a | ~c)) + blocks[11] - 1120210379;
|
||||
d = (d << 10 | d >>> 22) + a << 0;
|
||||
c += (a ^ (d | ~b)) + blocks[2] + 718787259;
|
||||
c = (c << 15 | c >>> 17) + d << 0;
|
||||
b += (d ^ (c | ~a)) + blocks[9] - 343485551;
|
||||
b = (b << 21 | b >>> 11) + c << 0;
|
||||
|
||||
if (this.first) {
|
||||
this.h0 = a + 1732584193 << 0;
|
||||
this.h1 = b - 271733879 << 0;
|
||||
this.h2 = c - 1732584194 << 0;
|
||||
this.h3 = d + 271733878 << 0;
|
||||
this.first = false;
|
||||
} else {
|
||||
this.h0 = this.h0 + a << 0;
|
||||
this.h1 = this.h1 + b << 0;
|
||||
this.h2 = this.h2 + c << 0;
|
||||
this.h3 = this.h3 + d << 0;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @method hex
|
||||
* @memberof Md5
|
||||
* @instance
|
||||
* @description Output hash as hex string
|
||||
* @returns {String} Hex string
|
||||
* @see {@link md5.hex}
|
||||
* @example
|
||||
* hash.hex();
|
||||
*/
|
||||
Md5.prototype.hex = function () {
|
||||
this.finalize();
|
||||
|
||||
var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3;
|
||||
|
||||
return HEX_CHARS[(h0 >> 4) & 0x0F] + HEX_CHARS[h0 & 0x0F] +
|
||||
HEX_CHARS[(h0 >> 12) & 0x0F] + HEX_CHARS[(h0 >> 8) & 0x0F] +
|
||||
HEX_CHARS[(h0 >> 20) & 0x0F] + HEX_CHARS[(h0 >> 16) & 0x0F] +
|
||||
HEX_CHARS[(h0 >> 28) & 0x0F] + HEX_CHARS[(h0 >> 24) & 0x0F] +
|
||||
HEX_CHARS[(h1 >> 4) & 0x0F] + HEX_CHARS[h1 & 0x0F] +
|
||||
HEX_CHARS[(h1 >> 12) & 0x0F] + HEX_CHARS[(h1 >> 8) & 0x0F] +
|
||||
HEX_CHARS[(h1 >> 20) & 0x0F] + HEX_CHARS[(h1 >> 16) & 0x0F] +
|
||||
HEX_CHARS[(h1 >> 28) & 0x0F] + HEX_CHARS[(h1 >> 24) & 0x0F] +
|
||||
HEX_CHARS[(h2 >> 4) & 0x0F] + HEX_CHARS[h2 & 0x0F] +
|
||||
HEX_CHARS[(h2 >> 12) & 0x0F] + HEX_CHARS[(h2 >> 8) & 0x0F] +
|
||||
HEX_CHARS[(h2 >> 20) & 0x0F] + HEX_CHARS[(h2 >> 16) & 0x0F] +
|
||||
HEX_CHARS[(h2 >> 28) & 0x0F] + HEX_CHARS[(h2 >> 24) & 0x0F] +
|
||||
HEX_CHARS[(h3 >> 4) & 0x0F] + HEX_CHARS[h3 & 0x0F] +
|
||||
HEX_CHARS[(h3 >> 12) & 0x0F] + HEX_CHARS[(h3 >> 8) & 0x0F] +
|
||||
HEX_CHARS[(h3 >> 20) & 0x0F] + HEX_CHARS[(h3 >> 16) & 0x0F] +
|
||||
HEX_CHARS[(h3 >> 28) & 0x0F] + HEX_CHARS[(h3 >> 24) & 0x0F];
|
||||
};
|
||||
|
||||
/**
|
||||
* @method toString
|
||||
* @memberof Md5
|
||||
* @instance
|
||||
* @description Output hash as hex string
|
||||
* @returns {String} Hex string
|
||||
* @see {@link md5.hex}
|
||||
* @example
|
||||
* hash.toString();
|
||||
*/
|
||||
Md5.prototype.toString = Md5.prototype.hex;
|
||||
|
||||
/**
|
||||
* @method digest
|
||||
* @memberof Md5
|
||||
* @instance
|
||||
* @description Output hash as bytes array
|
||||
* @returns {Array} Bytes array
|
||||
* @see {@link md5.digest}
|
||||
* @example
|
||||
* hash.digest();
|
||||
*/
|
||||
Md5.prototype.digest = function () {
|
||||
this.finalize();
|
||||
|
||||
var h0 = this.h0, h1 = this.h1, h2 = this.h2, h3 = this.h3;
|
||||
return [
|
||||
h0 & 0xFF, (h0 >> 8) & 0xFF, (h0 >> 16) & 0xFF, (h0 >> 24) & 0xFF,
|
||||
h1 & 0xFF, (h1 >> 8) & 0xFF, (h1 >> 16) & 0xFF, (h1 >> 24) & 0xFF,
|
||||
h2 & 0xFF, (h2 >> 8) & 0xFF, (h2 >> 16) & 0xFF, (h2 >> 24) & 0xFF,
|
||||
h3 & 0xFF, (h3 >> 8) & 0xFF, (h3 >> 16) & 0xFF, (h3 >> 24) & 0xFF
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* @method array
|
||||
* @memberof Md5
|
||||
* @instance
|
||||
* @description Output hash as bytes array
|
||||
* @returns {Array} Bytes array
|
||||
* @see {@link md5.array}
|
||||
* @example
|
||||
* hash.array();
|
||||
*/
|
||||
Md5.prototype.array = Md5.prototype.digest;
|
||||
|
||||
/**
|
||||
* @method arrayBuffer
|
||||
* @memberof Md5
|
||||
* @instance
|
||||
* @description Output hash as ArrayBuffer
|
||||
* @returns {ArrayBuffer} ArrayBuffer
|
||||
* @see {@link md5.arrayBuffer}
|
||||
* @example
|
||||
* hash.arrayBuffer();
|
||||
*/
|
||||
Md5.prototype.arrayBuffer = function () {
|
||||
this.finalize();
|
||||
|
||||
var buffer = new ArrayBuffer(16);
|
||||
var blocks = new Uint32Array(buffer);
|
||||
blocks[0] = this.h0;
|
||||
blocks[1] = this.h1;
|
||||
blocks[2] = this.h2;
|
||||
blocks[3] = this.h3;
|
||||
return buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
* @method buffer
|
||||
* @deprecated This maybe confuse with Buffer in node.js. Please use arrayBuffer instead.
|
||||
* @memberof Md5
|
||||
* @instance
|
||||
* @description Output hash as ArrayBuffer
|
||||
* @returns {ArrayBuffer} ArrayBuffer
|
||||
* @see {@link md5.buffer}
|
||||
* @example
|
||||
* hash.buffer();
|
||||
*/
|
||||
Md5.prototype.buffer = Md5.prototype.arrayBuffer;
|
||||
|
||||
/**
|
||||
* @method base64
|
||||
* @memberof Md5
|
||||
* @instance
|
||||
* @description Output hash as base64 string
|
||||
* @returns {String} base64 string
|
||||
* @see {@link md5.base64}
|
||||
* @example
|
||||
* hash.base64();
|
||||
*/
|
||||
Md5.prototype.base64 = function () {
|
||||
var v1, v2, v3, base64Str = '', bytes = this.array();
|
||||
for (var i = 0; i < 15;) {
|
||||
v1 = bytes[i++];
|
||||
v2 = bytes[i++];
|
||||
v3 = bytes[i++];
|
||||
base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] +
|
||||
BASE64_ENCODE_CHAR[(v1 << 4 | v2 >>> 4) & 63] +
|
||||
BASE64_ENCODE_CHAR[(v2 << 2 | v3 >>> 6) & 63] +
|
||||
BASE64_ENCODE_CHAR[v3 & 63];
|
||||
}
|
||||
v1 = bytes[i];
|
||||
base64Str += BASE64_ENCODE_CHAR[v1 >>> 2] +
|
||||
BASE64_ENCODE_CHAR[(v1 << 4) & 63] +
|
||||
'==';
|
||||
return base64Str;
|
||||
};
|
||||
|
||||
var exports = createMethod();
|
||||
|
||||
if (COMMON_JS) {
|
||||
module.exports = exports;
|
||||
} else {
|
||||
/**
|
||||
* @method md5
|
||||
* @description Md5 hash function, export to global in browsers.
|
||||
* @param {String|Array|Uint8Array|ArrayBuffer} message message to hash
|
||||
* @returns {String} md5 hashes
|
||||
* @example
|
||||
* md5(''); // d41d8cd98f00b204e9800998ecf8427e
|
||||
* md5('The quick brown fox jumps over the lazy dog'); // 9e107d9d372bb6826bd81d3542a419d6
|
||||
* md5('The quick brown fox jumps over the lazy dog.'); // e4d909c290d0fb1ca068ffaddf22cbd0
|
||||
*
|
||||
* // It also supports UTF-8 encoding
|
||||
* md5('中文'); // a7bac2239fcdcb3a067903d8077c4a07
|
||||
*
|
||||
* // It also supports byte `Array`, `Uint8Array`, `ArrayBuffer`
|
||||
* md5([]); // d41d8cd98f00b204e9800998ecf8427e
|
||||
* md5(new Uint8Array([])); // d41d8cd98f00b204e9800998ecf8427e
|
||||
*/
|
||||
root.md5 = exports;
|
||||
if (AMD) {
|
||||
define(function () {
|
||||
return exports;
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
||||
5
blade-core-oauth2/src/main/resources/static/js/popper.min.js
vendored
Normal file
5
blade-core-oauth2/src/main/resources/static/js/popper.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,65 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BladeX 统一认证系统</title>
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/iofrm-style.css">
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/iofrm-theme.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="form-body">
|
||||
<div class="row">
|
||||
<div class="form-holder">
|
||||
<div class="form-content">
|
||||
<div class="form-items">
|
||||
<div class="website-logo-inside">
|
||||
<img class="logo-size" src="/static/images/bladex-logo.png">
|
||||
<h1>BladeX 统一认证系统</h1>
|
||||
</div>
|
||||
<p th:text="'应用 [' + ${client_id} + '] 请求授权'">应用 [未获取到应用信息] 请求授权</p>
|
||||
<p>授权后该应用将取得系统操作权限</p>
|
||||
<div class="page-links">
|
||||
<a th:text="'授权账号 [' + ${username} + '] 请求授权'">授权账号 [未获取到账号信息]</a>
|
||||
</div>
|
||||
<form action="/oauth/authorize/perform" method="post">
|
||||
<input name='approval' value='true' type='hidden'/>
|
||||
<input id='state' name='state' th:value="${state}" type='hidden'/>
|
||||
<div class="form-button">
|
||||
<button id="submit" type="submit" class="ibtn">同意/授权</button>
|
||||
<button id="logout" class="lbtn">退出登录</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="other-links">
|
||||
<span>Copyrights © 2024 <a href="https://bladex.cn" target="_blank">BladeX</a> All Rights Reserved.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
<script src="/static/js/popper.min.js"></script>
|
||||
<script src="/static/js/bootstrap.min.js"></script>
|
||||
<script>
|
||||
$(window).on("load", function () {
|
||||
// 初始化页面增加租户id传递
|
||||
const state = getUrlParam("state");
|
||||
if (state !== null && state !== "") {
|
||||
$("#state").val(state);
|
||||
}
|
||||
});
|
||||
|
||||
$("#logout").click(function(){
|
||||
window.location.href = "/oauth/authorize/logout";
|
||||
});
|
||||
|
||||
// 获取url中参数的值
|
||||
function getUrlParam(name) {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
return urlParams.get(name);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
45
blade-core-oauth2/src/main/resources/templates/error.html
Normal file
45
blade-core-oauth2/src/main/resources/templates/error.html
Normal file
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BladeX 统一认证系统</title>
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/iofrm-style.css">
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/iofrm-theme.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="form-body">
|
||||
<div class="row">
|
||||
<div class="form-holder">
|
||||
<div class="form-content">
|
||||
<div class="form-items">
|
||||
<div class="website-logo-inside">
|
||||
<img class="logo-size" src="/static/images/bladex-logo.png">
|
||||
<h1>BladeX 统一认证系统</h1>
|
||||
</div>
|
||||
<p>应用授权失败</p>
|
||||
<div class="page-links">
|
||||
<a>请返回 [认证页面] 重新认证</a>
|
||||
</div>
|
||||
<div class="form-button">
|
||||
<button id="logout" class="lbtn">前往认证</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="other-links">
|
||||
<span>Copyrights © 2024 <a href="https://bladex.cn" target="_blank">BladeX</a> All Rights Reserved.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
<script src="/static/js/popper.min.js"></script>
|
||||
<script src="/static/js/bootstrap.min.js"></script>
|
||||
<script>
|
||||
$("#logout").click(function(){
|
||||
window.location.href = "/oauth/authorize/logout";
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
55
blade-core-oauth2/src/main/resources/templates/login.html
Normal file
55
blade-core-oauth2/src/main/resources/templates/login.html
Normal file
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BladeX 统一认证系统</title>
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/iofrm-style.css">
|
||||
<link rel="stylesheet" type="text/css" href="/static/css/iofrm-theme.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="form-body">
|
||||
<div class="row">
|
||||
<div class="form-holder">
|
||||
<div class="form-content">
|
||||
<div class="form-items">
|
||||
<div class="website-logo-inside">
|
||||
<img class="logo-size" src="/static/images/bladex-logo.png">
|
||||
<h1>BladeX 统一认证系统</h1>
|
||||
</div>
|
||||
<p>欢迎使用统一认证,提交后请对应用进行授权</p>
|
||||
<div class="page-links">
|
||||
<a>请输入认证信息</a>
|
||||
</div>
|
||||
<form id="form" action="/oauth/login/perform" method="post">
|
||||
<input class="form-control" type="text" name="tenant_id" placeholder="请输入租户ID" required>
|
||||
<input class="form-control" type="text" name="username" placeholder="请输入用户名" required>
|
||||
<input class="form-control" id="ipt" type="password" name="password" placeholder="请输入密码" required>
|
||||
<div class="form-button">
|
||||
<button id="btn" type="button" class="ibtn">登 录</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="other-links">
|
||||
<span>Copyrights © 2024 <a href="https://bladex.cn" target="_blank">BladeX</a> All Rights Reserved.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
<script src="/static/js/popper.min.js"></script>
|
||||
<script src="/static/js/bootstrap.min.js"></script>
|
||||
<script src="/static/js/md5.js"></script>
|
||||
<script>
|
||||
$("#btn").click(function(){
|
||||
const val = $("#ipt").val();
|
||||
$("#ipt").val(md5(val));
|
||||
$("#btn").attr("disabled", "disabled");
|
||||
$("#btn").text("登 录 中");
|
||||
$("#form").submit();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user