日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

oauth2单点登录总结

發布時間:2024/1/8 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 oauth2单点登录总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

OAuth 2.0授權框架支持第三方支持訪問有限的HTTP服務,通過在資源所有者和HTTP服務之間進行一個批準交互來代表資源者去訪問這些資源,或者通過允許第三方應用程序以自己的名義獲取訪問權限。

?

1.認證授權服務配置

主要配置繼承AuthorizationServerConfigurerAdapter的三個配置,其他的屬于配置類中方法或參數的加強和修飾。

package com.panda.admin.login.authconfig;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; import org.springframework.security.oauth2.provider.ClientDetailsService; import org.springframework.security.oauth2.provider.token.TokenEnhancer; import org.springframework.security.oauth2.provider.token.TokenEnhancerChain; import org.springframework.security.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;import java.util.Arrays;/*** author: tcy* createDate: 2022/10/26* description:認證授權服務配置*/ @Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate AuthenticationManager authenticationManager;@Autowiredprivate PasswordEncoder passwordEncoder;@Autowiredprivate ClientDetailsService clientDetailsService;@Autowiredprivate SysUserDetailServiceImpl sysUserDetailService;/*** redis工廠*/@Autowiredprivate RedisConnectionFactory redisConnectionFactory;/*** 用來配置令牌的安全約束* 攔截控制*/@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) {security.checkTokenAccess("permitAll()") // check_token公開.tokenKeyAccess("permitAll()") // token_key公開.allowFormAuthenticationForClients(); // 表單認證(申請令牌)}/*** 用來配置客戶端詳情服務(ClientDetailsService)* 允許客戶端自己申請ClientID*/@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {/*** 數據庫中添加客戶端信息表,可以啟用withClientDetails* 還需要自己建立ClientDetailsService的實現類ClientDetailsServiceImpl* ClientDetailsServiceImpl implements ClientDetailsService* 在實現類中將客戶端相關數據配置好*///clients.withClientDetails(clientDetailsService);/*** 客戶端配置唯一,直接在代碼中配置也可以* 但是保密性不強,安全性不高*/clients.inMemory().withClient("client") //注冊客戶端id.secret(passwordEncoder.encode("secret")) //注冊客戶端密碼.accessTokenValiditySeconds(60) //有效時間60秒,測試階段容易看出效果.authorizedGrantTypes("authorization_code","password","refresh_token") //三方登錄、密碼授權、刷新令牌.autoApprove(true) //登錄后繞過批準詢問(/oauth/confirm_access).scopes("all") //允許授權范圍.redirectUris("https://gitee.com/"); //回調網址,攜帶授權碼}/*** 管理令牌:用來配置令牌(token)的訪問端點和令牌服務(token services)*/@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {//token增強TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer(), jwtAccessTokenConverter()));endpoints.authenticationManager(authenticationManager).accessTokenConverter(jwtAccessTokenConverter()).tokenStore(tokenStore()).tokenEnhancer(tokenEnhancerChain)/** refresh token有兩種使用方式:重復使用(true)、非重復使用(false),默認為true* 1 重復使用:access token過期刷新時, refresh token過期時間未改變,仍以初次生成的時間為準* 2 非重復使用:access token過期刷新時, refresh token過期時間延續,在refresh token有效期內刷新便永不失效達到無需再次登錄的目的*/.reuseRefreshTokens(true).userDetailsService(sysUserDetailService);}/*** 自定義的Token增強器,把更多信息放入Token中* 登錄者的id、角色、手機號、其他綁定賬號等*/@Beanpublic TokenEnhancer tokenEnhancer() {return new EnhanceTokenEnhancer();}/*** 配置JWT令牌*/@Beanprotected JwtAccessTokenConverter jwtAccessTokenConverter() {//設置jwt的轉換器JwtAccessTokenConverter converter = new JwtAccessTokenConverter();/*** 非對稱加密:密鑰庫中獲取密鑰對(公鑰+私鑰)* 需要 *.jks文件*///KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("jks/jwt.jks"), "123456".toCharArray());//KeyPair keyPair = keyStoreKeyFactory.getKeyPair("jwt","888888".toCharArray()); //設置獲取秘鑰的密碼//converter.setKeyPair(keyPair); //設置秘鑰對象/*** 對稱加密*/converter.setSigningKey("Tu");return converter;}/*** JWT令牌存儲*/@Beanpublic TokenStore tokenStore() {/*** springSecurity中TokenStore實現有4種,分別是:* InMemoryTokenStore(保存本地內存)* JdbcTokenStore(保存到數據庫)* JwkTokenStore(全部信息返回到客戶端)* RedisTokenStore(保存到redis)*///存放至redis庫,注意pom和yml中相關配置RedisTokenStore redisTokenStore = new RedisTokenStore(redisConnectionFactory);redisTokenStore.setPrefix("auth:token:access:");return redisTokenStore;//return new JwtTokenStore(jwtAccessTokenConverter());}}

2.安全配置

主要為密碼、身份認證、請求放行

package com.panda.admin.login.authconfig;import com.panda.admin.login.auth.service.impl.SysUserDetailServiceImpl; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.dao.DaoAuthenticationProvider; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.factory.PasswordEncoderFactories; import org.springframework.security.crypto.password.PasswordEncoder;import javax.annotation.Resource;/*** author: tcy* createDate: 2022/10/27* description:安全配置*/ @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Resourceprivate SysUserDetailServiceImpl sysUserDetailService;/*** 密碼編碼器** 委托方式,根據密碼的前綴選擇對應的encoder,* 例如:{bcypt}前綴->標識BCYPT算法加密;* {noop}->標識不使用任何加密即明文的方式*/@Beanpublic PasswordEncoder passwordEncoder() {//秘文編輯密碼//return new BCryptPasswordEncoder();//編輯工廠,可用多種方式編輯return PasswordEncoderFactories.createDelegatingPasswordEncoder();}/*** 認證管理器*/@Beanpublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}/*** 身份驗證管理器*/@Overridepublic void configure(AuthenticationManagerBuilder auth) throws Exception {/*** 測試用戶,單獨提供* 只能用這個用戶才能登錄*///auth.inMemoryAuthentication()// .withUser("panda")// .password(passwordEncoder().encode("123456"))// .roles("admin");/*** 這里從數據庫查詢用戶,但是登錄方式唯一*///auth.userDetailsService(sysUserDetailService);/*** 可以匹配多種登錄方式* 賬號密碼、手機驗證碼、第三方授權等*/auth.authenticationProvider(daoAuthenticationProvider());}/*** 賬號密碼 認證授權提供者*/@Beanpublic DaoAuthenticationProvider daoAuthenticationProvider(){DaoAuthenticationProvider provider = new DaoAuthenticationProvider();provider.setUserDetailsService(sysUserDetailService);provider.setPasswordEncoder(passwordEncoder());provider.setHideUserNotFoundExceptions(false); //是否隱藏用戶不存在異常return provider;}/*** 配置放行規則*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/oauth/**").permitAll().antMatchers("/login/**").permitAll().antMatchers("/webjars/**", "/doc.html", "/swagger-resources", "/v2/api-docs","swagger-ui.html").permitAll().antMatchers("/actuator/**","/instances/**").permitAll().anyRequest().authenticated().and().csrf().disable();}@Override@Beanpublic UserDetailsService userDetailsService(){return super.userDetailsService();} }

3.token增強

這部分可以直接放在AuthorizationServerConfig的token增強器中

package com.panda.admin.login.authconfig;import com.panda.admin.login.constant.SecurityConstants; import org.springframework.security.core.Authentication; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.token.TokenEnhancer;import java.util.HashMap; import java.util.Map;/*** author: tcy* createDate: 2022/10/26* description:Token增強器*/ public class EnhanceTokenEnhancer implements TokenEnhancer {@Overridepublic OAuth2AccessToken enhance(OAuth2AccessToken oAuth2AccessToken, OAuth2Authentication oAuth2Authentication) {Authentication userAuthentication = oAuth2Authentication.getUserAuthentication();if (userAuthentication != null) {Map<String, Object> additionalInfo = new HashMap<>();additionalInfo.put(SecurityConstants.DETAILS_USER_ID, 2629738803L);additionalInfo.put(SecurityConstants.DETAILS_USERNAME, "承天永明");additionalInfo.put(SecurityConstants.DETAILS_NICKNAME, "颯颯");additionalInfo.put(SecurityConstants.OPEN_ID, "123456789");additionalInfo.put(SecurityConstants.ROLE_ID, "1");additionalInfo.put(SecurityConstants.MOBILE, "19108217140");((DefaultOAuth2AccessToken) oAuth2AccessToken).setAdditionalInformation(additionalInfo);}return oAuth2AccessToken;} }

4.登錄客戶的信息

package com.panda.admin.login.auth.Details;import com.panda.admin.login.SystemUser; import lombok.Data; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails;import java.io.Serializable; import java.util.Collection;/*** author: tcy* createDate: 2022/11/9* description:系統管理用戶認證信息*/ @Data public class SysUserDetails implements UserDetails, Serializable {private static final long serialVersionUID = 1L;private Long id;private String nickName;/*** UserDetails默認字段*/private String username;private String password;private Collection<SimpleGrantedAuthority> authorities;public SysUserDetails(SystemUser user){this.setId(user.getId());this.setUsername(user.getNickname());//數據表中,賬號為account字段this.setUsername(user.getAccount());this.setPassword(user.getPassword());}@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {return this.authorities;}//獲取密碼@Overridepublic String getPassword() {return this.password;}//獲取用戶名@Overridepublic String getUsername() {return this.username;}//賬號是否可用@Overridepublic boolean isAccountNonExpired() {return true;}//賬號是否鎖定@Overridepublic boolean isAccountNonLocked() {return true;}//憑證是否過期@Overridepublic boolean isCredentialsNonExpired() {return true;}//用戶是否正常@Overridepublic boolean isEnabled() {return true;} }

5.系統用戶信息查詢

package com.panda.admin.login.auth.service.impl;import cn.hutool.core.util.ObjectUtil; import com.panda.admin.login.SystemUser; import com.panda.admin.login.auth.Details.SysUserDetails; import com.panda.admin.result.ServiceException; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils;import javax.annotation.Resource;/*** author: tcy* createDate: 2022/11/9* description:系統用戶信息*/ @Service public class SysUserDetailServiceImpl implements UserDetailsService {@Resourceprivate SystemUserServiceImpl systemUserService;/*** 賬號密碼 認證*/@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {SysUserDetails sysUserDetails = null;//查詢用戶存在SystemUser systemUser = this.systemUserService.lambdaQuery().eq(SystemUser::getAccount, username).one();if (ObjectUtil.isNotEmpty(systemUser)){sysUserDetails = new SysUserDetails(systemUser);}if (ObjectUtils.isEmpty(systemUser) || ObjectUtils.isEmpty(sysUserDetails)){throw new ServiceException("用戶不存在");}return sysUserDetails;} }

6.明文密碼獲取token

/token/oauth接口是oauth2配置自帶,不用建立相關接口,只需要模塊的本地接口對上

(1)在用戶表中創建用戶數據,密碼為明文

(2)在系統用戶信息SysUserDetailServiceImpl中添加以下內容,{noop}表示不加密

if (ObjectUtil.isNotEmpty(systemUser)){systemUser.setPassword("{noop}" + systemUser.getPassword());sysUserDetails = new SysUserDetails(systemUser); }

(3)使用apifox,配置用戶信息,配置客戶端信息,然后發送請求

?

得到的結果:

?7.建立秘文密碼用戶數據

(1)建立秘文接口

package com.panda.admin.login.auth.controller;import io.swagger.annotations.Api; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;/*** author: tcy* createDate: 2022/11/9* description:*/ @Api(tags = "安全") @RestController @RequestMapping("/test") public class TestController {@Autowiredprivate PasswordEncoder passwordEncoder;@PostMapping("/info")public String info(){String secret = passwordEncoder.encode("tcy510823");return secret;} }

(2)apifox中建立相關請求,將第6步獲取的token放在請求頭Authorization中,注意:bearer + token。

?(3)復制秘文密碼,在數據庫中建立用戶數據

?

8.秘文密碼獲取token

(1)去掉SysUserDetailServiceImpl中的不加密操作

systemUser.setPassword("{noop}" + systemUser.getPassword());

(2)更換用戶信息發送請求

?

9.校驗token

(1)/oauth/check_token為oauth2自帶接口

(2)可以加工,得到適合的反饋效果

@Api(tags = "oauth登錄安全") @RestController @RequestMapping("/oauth") public class SystemUserController {@AutowiredTokenStore tokenStore;@ApiOperation(value = "校驗token")@GetMapping("/check_token")public Result<String> checkToken(@RequestParam("token") String token) {OAuth2AccessToken oAuth2AccessToken = this.tokenStore.readAccessToken(token);if (ObjectUtils.isEmpty(oAuth2AccessToken) || oAuth2AccessToken.isExpired()){throw new ServiceException("token無法識別或已經過期");}OAuth2Authentication oAuth2Authentication = this.tokenStore.readAuthentication(token);if (ObjectUtils.isEmpty(oAuth2Authentication)){throw new ServiceException("驗證信息無效或已過期");}int expiresIn = oAuth2AccessToken.getExpiresIn();return Result.success("token校驗通過,有效時間:" + expiresIn + "s");}}

(3)復制上面得到的token,放入請求參數中

?(4)結果

?

10.刷新token

(1)使用http://localhost:9001/oauth/token接口

(2)grant_type需要換成refresh_token

(3)refresh_token的值為之前請求,獲取的refresh_token

(4)結果,注意:"expires_in": 59?

?

總結

以上是生活随笔為你收集整理的oauth2单点登录总结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。