SpringSecurity
æ´å
OAuth2
æ¯å¼åè å ¬è®¤ç
èµæºä¿æ¤
ã
æå¡è®¤è¯
çæä½³æé ä¼ä¼´ï¼è¿å¯¹å¥½åºåä¸ç´å¨é»é»çå®æ¤çåºç¨æå¡çå®å ¨ï¼æ ¹æ®è®¿é®è çä¸åè§è²å¯ä»¥é¢ç²åº¦æ§å¶å°å ·ä½çæ¥å£ï¼ä»èå®ç°æéçç»å¾®ååã
è
SpringSecurity
æ¡æ¶å¨å®å ¨æ¡æ¶çéä¼ä¸ç®æ¯å ¥é¨æ¯è¾é«çï¼è½ç¶
Spring
éè¿
SpringBoot
è¿è¡äºå°è£ ï¼ä½æ¯ä½¿ç¨èµ·æ¥è¿æ¯æå¾å¤å®¹æéæ¼çé ç½®ï¼å 为é ç½®æ¯è¾å¤ï¼è®©åå¦è ç解起æ¥ä¹æ¯è¾å°é¾ï¼é对è¿ä¸ªé®é¢
ApiBoot
对
SpringSecurity
以å
OAuth2
è¿è¡äºå°è£ ï¼å¨åºç¡ä¸æ大çç®åäºé ç½®(åªåç®åãå¢å¼ºï¼
SpringSecurity
çåºç¡è¯æ³ãé ç½®è¿å¯ä»¥æ£å¸¸ä½¿ç¨)
å建项ç®
使ç¨
IDEA
å¼åå·¥å ·å建ä¸ä¸ª
SpringBoot
项ç®ã
çåºå±æ¯
ApiBoot
ï¼èä¸
SpringBoot
为äºæ¯æ
ApiBoot
ç
SpringBoot
åæ¯ï¼ä¹å¯¹åºçå建äº
2.2.x
åæ¯çæ¬ã
2.2.x
æ·»å ApiBootç»ä¸ä¾èµ
å建å®é¡¹ç®åæ们éè¦å¨
pom.xml
æ·»å
ApiBoot
çç»ä¸çæ¬ä¾èµï¼å¦ä¸æ示ï¼
org.minbox.framework
api-boot-dependencies
2.2.0.RELEASE
pom
import
æ·»å ç¸å ³ä¾èµ
æ¬ç« æ们éè¦æ¥è¯¢æ°æ®åºå çç¨æ·ä¿¡æ¯è¿è¡è®¤è¯ï¼æ以éè¦å¨
pom.xml
æ·»å æ°æ®åºç¸å ³çä¾èµï¼å¦ä¸æ示ï¼
org.springframework.boot
spring-boot-starter-web
org.minbox.framework
api-boot-starter-security-oauth-jwt
mysql
mysql-connector-java
com.zaxxer
HikariCP
org.minbox.framework
api-boot-starter-mybatis-enhance
å¨æ¬ç« 使ç¨å°äº
ApiBootMybatisEnhance
ï¼å ·ä½ç使ç¨è¯·è®¿é®å®æ¹ææ¡£ApiBoot MyBatis Enhance使ç¨ææ¡£
é ç½®æ°æ®æº
æ·»å æ°æ®åºç¸å ³çä¾èµåï¼å¨
application.yml
æ件å æ·»å å¦ä¸é 置信æ¯ï¼
spring:
application:
name: apiboot-security-oauth-custom-certification-user
# æ°æ®æºé
ç½®
datasource:
type: com.zaxxer.hikari.HikariDataSource
url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf8&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
server:
port: 9090
é ç½®ApiBoot Security
ApiBootSecurity
é»è®¤éç¨çæ¯
å
åæ¹å¼
(memory)读åç¨æ·ä¿¡æ¯ï¼æ们æ¬ç« éè¦ä¿®æ¹ä¸º
JDBC
æ¹å¼ï¼å¹¶ä¸
ç¦ç¨é»è®¤è¯»åç¨æ·ä¿¡æ¯
(
ApiBootSecurity
å é¨æä¾äºé»è®¤ç表ç»æï¼å»ºè¡¨åæ·»å æ°æ®å³å¯ç´æ¥ä½¿ç¨ç¨æ·ä¿¡æ¯è¿è¡è®¤è¯ï¼è¯¦è§ï¼ApiBoot Security使ç¨ææ¡£)ã
å¨
application.yml
é ç½®æ件ä¸æ·»å å¦ä¸é ç½®ï¼
# ApiBooté
ç½®
api:
boot:
security:
# ApiBoot Security 使ç¨JDBCæ¹å¼è¯»åç¨æ·
away: jdbc
# ç¦ç¨é»è®¤ç读åç¨æ·æ¹å¼
enable-default-store-delegate: false
api.boot.security.enable-default-store-delegate
é ç½®åæ°é»è®¤å¼ä¸º
true
ï¼ä¹å°±æ¯ä¼èªå¨è¯»åæ°æ®æºå¯¹åºæ°æ®åºå ç
api_boot_user_info
ç¨æ·ä¿¡æ¯è¡¨ï¼å½æ们设置为
false
åéè¦éè¿å®ç°
ApiBootStoreDelegate
æ¥å£æ¥è¿è¡èªå®ä¹æ¥è¯¢çç¨æ·ä¿¡æ¯ã
é ç½®ApiBoot OAuth
api-boot-starter-security-oauth-jwt
è¿ä¸ªä¾èµå é¨ä¹é»è®¤éæäº
OAuth2
ï¼èä¸é»è®¤çæ°æ®åå¨æ¹å¼ä¸
SpringSecurity
ä¸è´ä¹æ¯å åæ¹å¼(
memory
)ï¼æ们æ¬ç« ç主è¦ç®çæ¯æ¥è¯¢
认è¯ç¨æ·ä¿¡æ¯
ï¼èä¸æ¯
客æ·ç«¯ä¿¡æ¯
ï¼æ以æ们è¿æ¯éç¨é»è®¤çå åæ¹å¼ï¼ä¸è¿ä¿®æ¹ä¸å®¢æ·ç«¯çé»è®¤é 置信æ¯ï¼å¨
application.yml
æ件å æ·»å é ç½®å¦ä¸æ示ï¼
# ApiBooté
ç½®
api:
boot:
oauth:
# ApiBoot OAuth2ç客æ·ç«¯å表
clients:
- clientId: hengboy
clientSecret: chapter
grantTypes: password,refresh_token
å¨ä¸
ApiBoot
é»è®¤ç客æ·ç«¯é 置信æ¯ï¼å¯ä»¥éè¿æ¥ç
OAuth2
æºç äºè§£è¯¦æ ã
org.minbox.framework.api.boot.autoconfigure.oauth.ApiBootOauthProperties.Client
ç¨æ·è®¤è¯
é 置已ç»å®æï¼ä¸é¢æ们æ¥ç¼åæ¥è¯¢ç¨æ·ä¿¡æ¯ï¼å°ç¨æ·ä¿¡æ¯äº¤ç»
ApiBootSecurity
æ¡æ¶è¿è¡
认è¯
ã
çæAccessToken
çæä½ã
æ¬ç« 使ç¨çæä¹ åæ¡æ¶æ¯
ApiBootMyBatisEnhance
ï¼å ·ä½ç使ç¨æ¹æ³è¯·æ¥çå®æ¹ææ¡£ã
å建ç¨æ·è¡¨
æ们å¨æ°æ®åºå å建ä¸å¼ å为
system_user
çç³»ç»ç¨æ·ä¿¡æ¯è¡¨ï¼è¡¨ç»æå¦ä¸æ示ï¼
CREATE TABLE `system_user` (
`su_id` varchar(36) COLLATE utf8mb4_general_ci NOT NULL COMMENT 'ç¨æ·ç¼å·',
`su_login_name` varchar(30) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'ç»å½å',
`su_nick_name` varchar(30) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'æµç§°',
`su_password` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'ç¨æ·å¯ç ',
`su_create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´',
`su_status` int(11) DEFAULT '1' COMMENT 'ç¨æ·ç¶æï¼1ï¼æ£å¸¸ï¼0ï¼å»ç»ï¼-1ï¼å·²å é¤',
PRIMARY KEY (`su_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='ç³»ç»ç¨æ·ä¿¡æ¯è¡¨';
system_user
ç¨æ·è¡¨å建å®æåï¼æ们å¾è¿å¼ 表å æ·»å ä¸æ¡ç¨æ·æ°æ®ï¼å¦ä¸æ示ï¼
INSERT INTO `system_user` VALUES ('9b69fd26-14db-11ea-b743-dcd28627348e','yuqiyu','æå®å°å¹´ - äºèµ·å®','$2a$10$RbJGpi.v3PwkjrYENzOzTuMxazuanX3Qa2hwI/f55cYsZhFT/nX3.','2019-12-02 08:13:22',1);
æ们å¨ç»å½æ¶ç¨æ·å对åº
su_login_name
å段ï¼èå¯ç åæ¯å¯¹åº
su_password
å段ï¼
yuqiyu
è¿ä¸ªç¨æ·çå¯ç åå§å为
123456
ï¼å¯ç çæ ¼å¼å¿ 须为
BCryptPasswordEncoder
å å¯åçå¯æã
å建ç¨æ·å®ä½
é对
system_user
表æ们éè¦æ¥å建ä¸ä¸ª
ApiBootMyBatisEnhance
使ç¨çå®ä½ï¼å建ä¸ä¸ªå为
SystemUser
çå®ä½å¦ä¸æ示ï¼
@Data
@Table(name = "system_user")
public class SystemUser implements UserDetails {
@Id(generatorType = KeyGeneratorTypeEnum.UUID)
@Column(name = "su_id")
private String userId;
@Column(name = "su_login_name")
private String loginName;
@Column(name = "su_nick_name")
private String nickName;
@Column(name = "su_password")
private String password;
@Column(name = "su_create_time")
private String createTime;
@Column(name = "su_status")
private Integer status;
@Override
public Collection extends GrantedAuthority> getAuthorities() {
return Collections.EMPTY_LIST;
}
@Override
public String getUsername() {
return this.loginName;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return this.status == 1;
}
}
å ·ä½ç注解使ç¨è¯¦è§
ApiBootMyBatisEnhance
ææ¡£ï¼è¿éè¿ä¸ç¹éè¦æ³¨æçæ¯ï¼
SystemUser
å®ç°äº
UserDetails
æ¥å£ï¼å¦æ使ç¨è¿
SpringSecurity
çåå¦åºè¯¥é½ç¥éè¿æ¯
SpringSecurity
æä¾çç¨æ·è¯¦æ æ¥å£å®ä¹ï¼æ们å¦æ
èªå®ä¹æ¥è¯¢ç¨æ·
å°±åºè¯¥è®©æ们
èªå®ä¹çç¨æ·å®ä½
(注ï¼è¿æ¯çèªå®ä¹ç¨æ·å®ä½ä¹å°±æ¯SystemUserå®ä½)å®ç°è¿ä¸ªæ¥å£å¹¶å ¨é¨å®ç°
UserDetails
æ¥å£å æä¾çæ¹æ³ã
å建ç¨æ·æ°æ®æ¥å£
ç¨æ·çå®ä½å·²ç»å建å®æï¼æ们æ¬ç« éè¦ä¸ä¸ªæ ¹æ®ç¨æ·ç
ç»å½å
æ¥æ¥è¯¢ç¨æ·åºæ¬çæ°æ®æ¥å£ï¼å建ä¸ä¸ªå为
SystemUserEnhanceMapper
çæ¥å£å¦ä¸æ示ï¼
public interface SystemUserEnhanceMapper extends EnhanceMapper<SystemUser, Integer> {
SystemUser findByLoginName(@Param("loginName") String loginName);
}
该æ¥å£ç»§æ¿äº
EnhanceMapper<Entity,ID>
æ¥å£ï¼å¯ä»¥èªå¨è¢«æ«æå°
å建代ççå®ä¾
å并ä¸å å ¥
IOC
ï¼è¿æ ·æ们å¨é¡¹ç®å ¶ä»çå°æ¹å¯ä»¥ç´æ¥æ³¨å ¥ä½¿ç¨ã
注æï¼æ¹æ³æ¯
findByXxx
æä¾çæ¹æ³å½åè§åæ¥è¯¢ï¼å¤ä¸ªæ¥è¯¢æ¡ä»¶å¯ä»¥ä½¿ç¨
ApiBootMyBatisEnhance
æè
And
追å ï¼ä¼èªå¨æ ¹æ®æ¹æ³çè§åçæ对åºç
Or
ã
SQL
å®ç°ApiBootStoreDelegateæ¥å£
ApiBootSecurity
æä¾äºä¸ä¸ªæ¥å£
ApiBootStoreDelegate
ï¼è¿ä¸ªæ¥å£ä¸»è¦æ¯ç¨æ¥æ¥è¯¢ç»å½ç¨æ·çå ·ä½ä¿¡æ¯çä½ç¨ï¼å½æ们éè¿
grant_type=password&username=xxx
çæ¹å¼è¿è¡è·å
AccessToken
æ¶ï¼
ApiBootSecurity
ä¼ç´æ¥æ
username
çåæ°å¼ä¼ éç»
ApiBootStoreDelegate#loadUserByUsername
çæ¹æ³å ï¼è¿æ ·æ们就å¯ä»¥æ ¹æ®
username
è¿è¡æ¥è¯¢ç¨æ·å¹¶è¿åç»
ApiBootSecurity
ååç»ç认è¯æä½ã
æ们æ¥å建ä¸ä¸ªå为
UserService
ç类并å®ç°
ApiBootStoreDelegate
æ¥å£ï¼å¦ä¸æ示ï¼
@Service
public class UserService implements ApiBootStoreDelegate {
static Logger logger = LoggerFactory.getLogger(UserService.class);
@Autowired
private SystemUserEnhanceMapper mapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDetails userDetails = mapper.findByLoginName(username);
if (ObjectUtils.isEmpty(userDetails)) {
throw new UsernameNotFoundException("ç¨æ·ï¼" + username + "ï¼ä¸åå¨.");
}
logger.info("ç»å½ç¨æ·çä¿¡æ¯ï¼{}", JSON.toJSONString(userDetails));
return userDetails;
}
}
loadUserByUsername
æ¹æ³çè¿åå¼æ¯
UserDetails
æ¥å£ç±»åï¼å¨ä¹åæ们已ç»å°
SystemUser
å®ç°äºè¯¥æ¥å£ï¼æ以æ们å¯ä»¥ç´æ¥å°
SystemUser
å®ä¾ä½ä¸ºè¿åå¼ã
è¿è¡æµè¯
代ç ä¸å就绪ï¼éè¿
XxxxApplication
çæ¹å¼æ¥å¯å¨é¡¹ç®ã
æµè¯ç¹ï¼è·åAccessToken
å¨è·å
AccessToken
ä¹åï¼æ们éè¦ç¡®è®¤
application.yml
æ件å é ç½®ç
api.boot.oauth.clients
ç客æ·ç«¯ç
clientId
ã
clientSecret
é ç½®å 容ï¼ä¸é¢æ¯éè¿
CURL
çæ¹å¼ï¼
â ~ curl hengboy:[email protected]:9090/oauth/token -d 'grant_type=password&username=yuqiyu&password=123456'
{"access_token":"3beb1bee-9ca6-45e1-9fb8-5fc181670f63","token_type":"bearer","refresh_token":"d2243e18-8ab3-4842-a98f-ebd79da94e2e","expires_in":7199,"scope":"api"}
æµè¯ç¹ï¼å·æ°AccessToken
å¤å¶ä¸é¢è·åå°ç
refresh_token
çå¼è¿è¡å·æ°ï¼ä¸é¢æ¯å·æ°
AccessToken
ç
CURL
æ¹å¼ï¼
â ~ curl hengboy:[email protected]:9090/oauth/token -d 'grant_type=refresh_token&refresh_token=d2243e18-8ab3-4842-a98f-ebd79da94e2e'
{"access_token":"e842c2ee-5672-49db-a530-329186f36492","token_type":"bearer","refresh_token":"d2243e18-8ab3-4842-a98f-ebd79da94e2e","expires_in":7199,"scope":"api"}
è¿ä¸ª
hengboy
客æ·ç«¯å¨
OAuth2
ä¸éè¿é ç½®
application.yml
ææäºä¸¤ç§
grantTypes
ï¼åå«æ¯
grant_type
ã
password
ï¼å¦æéè¦å«çæ¹å¼å¯ä»¥å¨é ç½®æ件å 对åºæ·»å ã
refresh_token
æ²é»æ¿ï¼åéç¹
ApiBoot
æ´å
SpringSecurity
以å
OAuth2
å读åèªå®ä¹ç¨æ·ä¿¡æ¯ï¼æ们åªéè¦å ³æ³¨å ·ä½æä¹è¯»åç¨æ·ä¿¡æ¯ï¼ä¹åé£äºæµæµææç代ç é ç½®é½å¯ä»¥éè¿
é
ç½®æ件
çæ¹å¼ä»£æ¿ï¼æ¬ç« ç主è¦å 容æ¯
ApiBootStoreDelegate
è¿ä¸ªæ¥å£ï¼
ApiBoot
ææä¾çåè½è¿ä¸æ¢è¿äºï¼ä¼éç»å享ç»å¤§å®¶ã
å¦æä½ è§å¾ SpringSecurity è¿äºèè¿ï¼æ³ç¨ç®åå°å·§çå®å ¨æ¡æ¶ï¼ä¹å¯ä»¥ççè¿ç¯æç« ï¼ä¸ç¨ Spring Security å¯å¦ï¼è¯è¯è¿ä¸ªå°èç¾çå®å ¨æ¡æ¶
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5yYmhTNilDMjRTZjJjZxUWNjBjZ3Q2Y3QGN4YTOlVjM38CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)