Spring Cloud OAuth 2を使用してライセンスサービスを構築
10216 ワード
転載:https://www.cnblogs.com/fp2952/p/8973613.html 本文は主にspring cloud授権サービスの構築であり、jwt認証を採用する.
1.Spring Security Security OAuth 2の導入2.クラス注記オープン@EnableAuthorizationServer 3.Oauth 2構成クラスの起動
AuthorizationServerConfigurerAdapter ClientDetailsServiceConfigurer:クライアント詳細サービス(ClientDetailServices)を構成するためのものであり、クライアント詳細はここで初期化され、クライアント情報を書き込みまたはデータベースを介して呼び出し詳細情報を格納することができる. AuthorizationServerSecurityConfigurer:トークンエンドポイント(TokenEndpoint)を構成するためのセキュリティ制約 AuthorizationServerEndpointsConfigurer:ライセンスおよびトークンサービスを構成するための の主な構成は以下の通りである:ClientDetailsServiceConfigurer(AuthorizationServerConfigurerのコールバック構成)はメモリまたはJDBCを使用してクライアントの詳細サービス(ClientDetailsServices)を実現することができ、Spring Security OAuth 2の構成方法は@Configurationクラス継承AuthorizationServerConfigureAdaterを作成し、void configureを書き換えることである(C l e n t D e tailsServiceConfigurer clients)メソッド、たとえば: トークン管理の構成(JWTAccessTokenConverter)
JWTAccessTokenConverterはtokenを生成するための変換器であり、tokenトークンはデフォルトで署名されており、リソースサーバはこの署名を検証する必要がある.ここでの暗号化および検証には、対称暗号化、非対称暗号化(公開鍵暗号化)の2つの方法がある.対称暗号化には、認証サーバとリソースサーバが同じkey値を格納する必要があります.対称暗号化ではなく、鍵暗号化を使用して、公開鍵をリソースサーバに暴露して署名することができます.本明細書では、非対称暗号化方式を使用して、AuthOrizationServiceConfigurerAdapterに構成されています.
JDKツールでJKS証明書ファイルを生成し、keystore.jksをresourceディレクトリのkeytool-genkeypair-alias mytest-keyalg RSA-keypass mypass-keystore keystore.jks-storepass mypassここではJwtAccessTokenをカスタマイズして追加ユーザー情報を追加します
JwtAccessTokenクラスではauthenticationのgetPrincipal(実際にはUserDetailsインタフェース)からユーザ情報を取得するので、独自のUserDetailsを実現する必要があります
認可エンドポイントオープン
Security構成
DaoAuthenticationProvider、UserDetailServiceなどの構成が必要
UserDetailsService実装
認証サーバーの検証http://127.0.0.1:8080/oauth/authorize?client_id=clientId&response_type=code&redirect_uri=www.baidu.com
注意:client_id:データベースに格納されているclient_id、response_type:デッドコード
リンクして車に戻ってspring securityの簡単なログインページに入り、
アカウントのパスワードを入力して、UserDetailsServiceが取得するユーザーのためにloginをクリックして、簡単な授権ページに入って、Authorizeをクリックして、redirect_uriにリダイレクトして、codeパラメータを持っています:http://www.baidu.com?code=rTKETX postリクエストtoken:
なお、ここでは、Basic xxxがclient_id:client_secretのbase 64符号化の値であるAuthorizationリクエストヘッダを追加する必要がある.
1.Spring Security Security OAuth 2の導入2.クラス注記オープン@EnableAuthorizationServer 3.Oauth 2構成クラスの起動
AuthorizationServerConfigurerAdapter
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// JdbcClientDetailsService
clients.withClientDetails(new JdbcClientDetailsService(dataSource));
}
JWTAccessTokenConverterはtokenを生成するための変換器であり、tokenトークンはデフォルトで署名されており、リソースサーバはこの署名を検証する必要がある.ここでの暗号化および検証には、対称暗号化、非対称暗号化(公開鍵暗号化)の2つの方法がある.対称暗号化には、認証サーバとリソースサーバが同じkey値を格納する必要があります.対称暗号化ではなく、鍵暗号化を使用して、公開鍵をリソースサーバに暴露して署名することができます.本明細書では、非対称暗号化方式を使用して、AuthOrizationServiceConfigurerAdapterに構成されています.
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager)
// JwtAccessToken
.accessTokenConverter(jwtAccessTokenConverter())
// refresh_token userDetailsService
.reuseRefreshTokens(false).userDetailsService(userDetailsService);
//.tokenStore(getJdbcTokenStore());
}
/**
* Token
* @return
*/
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessToken();
//
KeyStoreKeyFactory keyStoreKeyFactory =
new KeyStoreKeyFactory(new ClassPathResource("keystore.jks"), "mypass".toCharArray());
converter.setKeyPair(keyStoreKeyFactory.getKeyPair("mytest"));
return converter;
}
JDKツールでJKS証明書ファイルを生成し、keystore.jksをresourceディレクトリのkeytool-genkeypair-alias mytest-keyalg RSA-keypass mypass-keystore keystore.jks-storepass mypassここではJwtAccessTokenをカスタマイズして追加ユーザー情報を追加します
/**
* Created by fp295 on 2018/4/16.
* JwtAccessToken
*/
public class JwtAccessToken extends JwtAccessTokenConverter {
/**
* token
* @param accessToken
* @param authentication
* @return
*/
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
DefaultOAuth2AccessToken defaultOAuth2AccessToken = new DefaultOAuth2AccessToken(accessToken);
//
BaseUser baseUser = ((BaseUserDetail) authentication.getPrincipal()).getBaseUser();
baseUser.setPassword(null);
// token
defaultOAuth2AccessToken.getAdditionalInformation().put(Constant.USER_INFO, baseUser);
return super.enhance(defaultOAuth2AccessToken, authentication);
}
/**
* token
* @param value
* @param map
* @return
*/
@Override
public OAuth2AccessToken extractAccessToken(String value, Map map){
OAuth2AccessToken oauth2AccessToken = super.extractAccessToken(value, map);
convertData(oauth2AccessToken, oauth2AccessToken.getAdditionalInformation());
return oauth2AccessToken;
}
private void convertData(OAuth2AccessToken accessToken, Map map) {
accessToken.getAdditionalInformation().put(Constant.USER_INFO,convertUserData(map.get(Constant.USER_INFO)));
}
private BaseUser convertUserData(Object map) {
String json = JsonUtils.deserializer(map);
BaseUser user = JsonUtils.serializable(json, BaseUser.class);
return user;
}
}
JwtAccessTokenクラスではauthenticationのgetPrincipal(実際にはUserDetailsインタフェース)からユーザ情報を取得するので、独自のUserDetailsを実現する必要があります
/**
* Created by fp295 on 2018/4/29.
* org.springframework.security.core.userdetails.User
*/
public class BaseUserDetail implements UserDetails, CredentialsContainer {
private final BaseUser baseUser;
private final org.springframework.security.core.userdetails.User user;
public BaseUserDetail(BaseUser baseUser, User user) {
this.baseUser = baseUser;
this.user = user;
}
@Override
public void eraseCredentials() {
user.eraseCredentials();
}
@Override
public Collection extends GrantedAuthority> getAuthorities() {
return user.getAuthorities();
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return user.isAccountNonExpired();
}
@Override
public boolean isAccountNonLocked() {
return user.isAccountNonLocked();
}
@Override
public boolean isCredentialsNonExpired() {
return user.isCredentialsNonExpired();
}
@Override
public boolean isEnabled() {
return user.isEnabled();
}
public BaseUser getBaseUser() {
return baseUser;
}
}
認可エンドポイントオープン
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer
// /oauth/token_key
.tokenKeyAccess("permitAll()")
// /oauth/check_token
.checkTokenAccess("isAuthenticated()");
}
Security構成
DaoAuthenticationProvider、UserDetailServiceなどの構成が必要
@Configuration
@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// UserDetailsService
@Autowired
private BaseUserDetailService baseUserDetailService;
@Override
public void configure(HttpSecurity http) throws Exception {
http // /login
.formLogin().permitAll()
//
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/")
//
.and().authorizeRequests().anyRequest().authenticated()
// JWT, csrf
.and().csrf().disable();
}
/**
*
* @param auth
*/
@Override
public void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(daoAuthenticationProvider());
}
@Bean
public DaoAuthenticationProvider daoAuthenticationProvider(){
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
// userDetailsService
provider.setUserDetailsService(baseUserDetailService);
//
provider.setHideUserNotFoundExceptions(false);
// BCrypt hash
provider.setPasswordEncoder(new BCryptPasswordEncoder(6));
return provider;
}
}
UserDetailsService実装
@Service
public class BaseUserDetailService implements UserDetailsService {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private BaseUserService baseUserService;
@Autowired
private BaseRoleService baseRoleService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// FeignClient
ResponseData baseUserResponseData = baseUserService.getUserByUserName(username);
if(baseUserResponseData.getData() == null || !ResponseCode.SUCCESS.getCode().equals(baseUserResponseData.getCode())){
logger.error(" , :" + username);
throw new UsernameNotFoundException(" , :" + username);
}
BaseUser baseUser = baseUserResponseData.getData();
// FeignClient
ResponseData> baseRoleListResponseData = baseRoleService.getRoleByUserId(baseUser.getId());
List roles;
if(baseRoleListResponseData.getData() == null || !ResponseCode.SUCCESS.getCode().equals(baseRoleListResponseData.getCode())){
logger.error(" !");
roles = new ArrayList<>();
}else {
roles = baseRoleListResponseData.getData();
}
//
List authorities = new ArrayList();
roles.forEach(e -> {
// 、 GrantedAuthority, GrantedAuthority
GrantedAuthority authority = new SimpleGrantedAuthority(e.getRoleCode());
authorities.add(authority);
});
// User
org.springframework.security.core.userdetails.User user = new org.springframework.security.core.userdetails.User(baseUser.getUserName(),
baseUser.getPassword(), isActive(baseUser.getActive()), true, true, true, authorities);
return new BaseUserDetail(baseUser, user);
}
private boolean isActive(int active){
return active == 1 ? true : false;
}
}
認証サーバーの検証http://127.0.0.1:8080/oauth/authorize?client_id=clientId&response_type=code&redirect_uri=www.baidu.com
注意:client_id:データベースに格納されているclient_id、response_type:デッドコード
リンクして車に戻ってspring securityの簡単なログインページに入り、
アカウントのパスワードを入力して、UserDetailsServiceが取得するユーザーのためにloginをクリックして、簡単な授権ページに入って、Authorizeをクリックして、redirect_uriにリダイレクトして、codeパラメータを持っています:http://www.baidu.com?code=rTKETX postリクエストtoken:
なお、ここでは、Basic xxxがclient_id:client_secretのbase 64符号化の値であるAuthorizationリクエストヘッダを追加する必要がある.