新聞中心
關(guān)于OAuth2不做介紹了,網(wǎng)絡(luò)太多了。

按需求定制設(shè)計可以根據(jù)自己的需求進(jìn)行定制,成都網(wǎng)站設(shè)計、成都網(wǎng)站制作、外貿(mào)網(wǎng)站建設(shè)構(gòu)思過程中功能建設(shè)理應(yīng)排到主要部位公司成都網(wǎng)站設(shè)計、成都網(wǎng)站制作、外貿(mào)網(wǎng)站建設(shè)的運用實際效果公司網(wǎng)站制作網(wǎng)站建立與制做的實際意義
環(huán)境:2.4.12 + OAuth2 + Redis
redis用來實現(xiàn)token的存儲。
- pom.xml
org.springframework.boot
spring-boot-starter-data-redis
org.apache.commons
commons-pool2
org.springframework.security.oauth.boot
spring-security-oauth2-autoconfigure
2.2.11.RELEASE
org.springframework.boot
spring-boot-starter-data-jpa
mysql
mysql-connector-java
net.sourceforge.nekohtml
nekohtml
org.springframework.boot
spring-boot-starter-thymeleaf
- application.yml
server:
port: 8208
---
spring:
application:
name: oauth-server
---
spring:
redis:
host: localhost
port: 6379
password:
database: 1
lettuce:
pool:
maxActive: 8
maxIdle: 100
minIdle: 10
maxWait: -1
---
spring:
resources:
staticLocations: classpath:/static/,classpath:/templates/,classpath:/pages/
mvc:
staticPathPattern: /resources/**
---
spring:
datasource:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8
username: root
password: 123456
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimumIdle: 10
maximumPoolSize: 200
autoCommit: true
idleTimeout: 30000
poolName: MasterDatabookHikariCP
maxLifetime: 1800000
connectionTimeout: 30000
connectionTestQuery: SELECT 1
jpa:
hibernate:
ddlAuto: update
showSql: true
openInView: true #Open EntityManager in View
---
spring:
thymeleaf:
servlet:
contentType: text/html; charset=utf-8
cache: false
mode: LEGACYHTML5
encoding: UTF-8
enabled: true
prefix: classpath:/pages/
suffix: .html
---
spring:
main:
allow-bean-definition-overriding: true
- 實體
@Entity
@Table(name = "T_APP")
public class App implements Serializable {
private static final long serialVersionUID = 1L ;
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id ;
/**
* 客戶端ID
*/
private String clientId ;
/**
* 客戶端密鑰
*/
private String clientSecret ;
/**
* 跳轉(zhuǎn)地址
*/
private String redirectUri ;
}
// 該實體用來存在每個應(yīng)用的信息。
@Entity
@Table(name = "T_USERS")
public class Users implements UserDetails, Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id ;
private String username ;
private String password ;
}
// 該實體是用戶登錄信息。
- DAO類
// 提供了一個方法,根據(jù)clientId獲取客戶端信息。
public interface AppRepository extends JpaRepository, JpaSpecificationExecutor {
App findByClientId(String clientId) ;
}
public interface UsersRepository extends JpaRepository, JpaSpecificationExecutor {
Users findByUsernameAndPassword(String username, String password) ;
}
- 核心配置類
重要代碼已經(jīng)加了注釋說明
@Configuration
@EnableAuthorizationServer
public class OAuthAuthorizationConfig extends AuthorizationServerConfigurerAdapter {
@Resource
private AppRepository appRepository ;
@Resource
private RedisConnectionFactory redisConnectionFactory ;
@Resource
private AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security)
throws Exception {
security.tokenKeyAccess("permitAll()") // isAuthenticated()
.checkTokenAccess("permitAll()") // 允許訪問 /oauth/check_token 接口
.allowFormAuthenticationForClients() ;
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
// 自定義CODE
endpoints.authorizationCodeServices(new InMemoryAuthorizationCodeServices() {
@Override
public String createAuthorizationCode(OAuth2Authentication authentication) {
String code = UUID.randomUUID().toString().replaceAll("-", "") ;
store(code, authentication) ;
return code;
}
}) ;
endpoints.exceptionTranslator(new DefaultWebResponseExceptionTranslator() {
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public ResponseEntity translate(Exception e) throws Exception {
ResponseEntity responseEntity = super.translate(e) ;
ResponseEntity
- 暴露一個AuthenticationManager類
密碼模式必須設(shè)置對應(yīng)的AuthenticationManager,所以這里必須暴露出來,否則系統(tǒng)找不到。
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
- 自定義ClientDetails
該類主要是用在配置類中定義 ClientDetailsService是為了簡化使用的。如下圖:
圖片
這里就是為了獲取當(dāng)前客戶端的所有信息使用。
public class OAuthClientDetails implements ClientDetails,Serializable {
private static final long serialVersionUID = 1L;
private String id ;
private String clientId ;
private boolean secretRequired ;
private String clientSecret ;
private boolean scoped ;
private Set resourceIds ;
private Set scope = new HashSet<>();
private Set authorizedGrantTypes = new HashSet<>();
private Set registeredRedirectUri = new HashSet<>();
private Collection authorities ;
private boolean autoApprove ;
private Integer accessTokenValiditySeconds ;
private Integer refreshTokenValiditySeconds ;
}
- 登錄認(rèn)證類
@Component
public class LoginAuthenticationProvider implements AuthenticationProvider {
@Resource
private UsersRepository usersRepository ;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// 登錄用戶名
String username = authentication.getName() ;
// 憑證(密碼)
Object credentials = authentication.getCredentials() ;
Users user = null ;
try {
user = usersRepository.findByUsernameAndPassword(username, (String) credentials) ;
if (user == null) {
String errorMsg = "錯誤的用戶名或密碼" ;
throw new BadCredentialsException(errorMsg) ;
}
} catch (Exception e) {
throw e ;
}
UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(
user, authentication.getCredentials(), Arrays.asList(
new SimpleGrantedAuthority("ROLE_USERS"),
new SimpleGrantedAuthority("ROLE_ACTUATOR")));
result.setDetails(authentication.getDetails());
return result;
}
@Override
public boolean supports(Class> authentication) {
return (UsernamePasswordAuthenticationToken.class
.isAssignableFrom(authentication));
}
}
- 密碼驗證
@Component
public class LoginPasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence rawPassword) {
return rawPassword.toString() ;
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return this.encode(rawPassword).equals(encodedPassword) ;
}
}
注意:
Users實體類為啥要實現(xiàn)UserDetails?
應(yīng)該我們在存儲token相關(guān)信息到redis時需要有對應(yīng)key的生成方式。
RedisTokenStore.java中有個默認(rèn)的key生成方式:
圖片
圖片
進(jìn)入上面的方法中:
圖片
進(jìn)入getName方法中:
圖片
最終它會調(diào)用紅色框中的代碼,這樣就出現(xiàn)一個問題,你每次獲取token的時候都會生成一個新的token。所以這里我們的Users實體實現(xiàn)了UserDetails接口。
圖片
這里是通過debug查看
到此整合完畢了!
測試:
先造兩條數(shù)據(jù):
圖片
圖片
- 授權(quán)碼模式
授權(quán)碼模式(authorization code)是功能最完整、流程最嚴(yán)密的授權(quán)模式。它的特點就是通過客戶端的后臺服務(wù)器,與"服務(wù)提供商"的認(rèn)證服務(wù)器進(jìn)行互動。
請求地址
圖片
訪問上面地址后跳轉(zhuǎn)到了登錄頁面
輸入正確的用戶名密碼后:
圖片
成功后跳到了我們配置的跳轉(zhuǎn)地址,這時候我們就可以根據(jù)地址欄的code獲取token了:
圖片
注意:這里的code是一次性的,也就是說如果使用過了就會自動失效。
- 密碼模式
密碼模式(Resource Owner Password Credentials Grant)中,用戶向客戶端提供自己的用戶名和密碼??蛻舳耸褂眠@些信息,向"服務(wù)商提供商"索要授權(quán)。
在這種模式中,用戶必須把自己的密碼給客戶端,但是客戶端不得儲存密碼。這通常用在用戶對客戶端高度信任的情況下,比如客戶端是操作系統(tǒng)的一部分,或者由一個著名公司出品。而認(rèn)證服務(wù)器只有在其他授權(quán)模式無法執(zhí)行的情況下,才能考慮使用這種模式。
圖片
- 客戶端模式
客戶端模式(Client Credentials Grant)指客戶端以自己的名義,而不是以用戶的名義,向"服務(wù)提供商"進(jìn)行認(rèn)證。嚴(yán)格地說,客戶端模式并不屬于OAuth框架所要解決的問題。在這種模式中,用戶直接向客戶端注冊,客戶端以自己的名義要求"服務(wù)提供商"提供服務(wù),其實不存在授權(quán)問題。
圖片
- 簡化模式
簡化模式(implicit grant type)不通過第三方應(yīng)用程序的服務(wù)器,直接在瀏覽器中向認(rèn)證服務(wù)器申請令牌,跳過了"授權(quán)碼"這個步驟,因此得名。所有步驟在瀏覽器中完成,令牌對訪問者是可見的,且客戶端不需要認(rèn)證。
圖片
簡化模式的流程,這樣有助于理解
(A)客戶端將用戶導(dǎo)向認(rèn)證服務(wù)器。
(B)用戶決定是否給予客戶端授權(quán)。
(C)假設(shè)用戶給予授權(quán),認(rèn)證服務(wù)器將用戶導(dǎo)向客戶端指定的"重定向URI",并在URI的Hash部分包含了訪問令牌。
(D)瀏覽器向資源服務(wù)器發(fā)出請求,其中不包括上一步收到的Hash值。
(E)資源服務(wù)器返回一個網(wǎng)頁,其中包含的代碼可以獲取Hash值中的令牌。
(F)瀏覽器執(zhí)行上一步獲得的腳本,提取出令牌。
(G)瀏覽器將令牌發(fā)給客戶端。
- 刷新令牌
如果用戶訪問的時候,客戶端的"訪問令牌"過期前,可以申請一個新的訪問令牌。
圖片
這里的refresh_token就是在獲取token的時候返回的。
網(wǎng)站題目:SpringBoot整合OAuth2實現(xiàn)單點登錄
文章分享:http://fisionsoft.com.cn/article/coipdoe.html


咨詢
建站咨詢
