javascript
nacos oaut服务地址_用户认证的例子:Spring Security oAuth2 + Spring Cloud Gateway + Nacos + Dubbo...
這個例子是商城后臺項目的一部分,主要使用了oAuth2的密碼模式完成用戶名密碼認證功能。主要流程是:使用Nacos作為注冊中心,操作用戶的服務user-mgr-service作為服務提供者,注冊到Nacos,通過Dubbo供oAuth2調用,同時oAuth2也作為Rest服務提供者,注冊到Nacos,提供用戶登錄/user/login服務。網關Gateway也注冊到Nacos,提供統一入口,路由到oAuth2服務,完成用戶認證。
(文章主要寫一下實現步驟,具體代碼附上的話太多了,影響閱讀。github.com/toyranger/c…)
1. Spring Security oAuth2 密碼模式
1.1 密碼模式和授權碼模式
{placeholder}
2. oAuth2實現認證服務器
2.1 創建授權服務器
ClientDetailsServiceConfigurer:通過配置的數據源,配置ClientDetailsService
AuthorizationServerSecurityConfigurer:用來配置令牌端點(Token Endpoint)的安全約束.
AuthorizationServerEndpointsConfigurer:用來配置授權(authorization)以及令牌(token)
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
private BCryptPasswordEncoder passwordEncoder;
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource());
}
@Bean
public ClientDetailsService jdbcClientDetailsService() {
return new JdbcClientDetailsService(dataSource());
}
/***
* 用于支持密碼模式
*/
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager).tokenStore(tokenStore());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
// 允許客戶端訪問 /oauth/check_token檢查token
security.checkTokenAccess("isAuthenticated()").allowFormAuthenticationForClients();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(jdbcClientDetailsService());
}
/***
* 內存模式
*/
// @Override
// public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//
// clients.inMemory()
// .withClient("client")
// .secret(passwordEncoder.encode("secret"))
// .authorizedGrantTypes("password", "refresh_token")
// .scopes("backend")
// .resourceIds("backend-resources")
// .accessTokenValiditySeconds(60 * 60 * 24)
// .refreshTokenValiditySeconds(60 * 60 * 24 * 30);
// }
}
復制代碼
2.2 創建認證服務器和資源服務器
認證服務器的任務是根據用戶名查詢用戶,以及用戶所具有的權限,資源服務器的任務是配置訪問資源(url)所需要的對應的權限。這里把他們寫在一個Configuration中
@Configuration
@EnableWebSecurity
@EnableResourceServer
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public UserDetailsService userDetailsService() {
return new UserDetailsServiceImpl();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService());
}
/***
* 用于支持 password 模式
* @return
* @throws Exception
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/user/login");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/user/info").hasAnyAuthority("UserInfo")
.antMatchers("/user/logout").hasAnyAuthority("UserLogout");
}
}
復制代碼
2.3 在用戶認證的userDetailsService中,需要通過Dubbo調用user-mgr-service提供的服務
public class UserDetailsServiceImpl implements UserDetailsService {
@Reference(version = "1.0.0")
private UserMgrApi userMgrApi;
@Reference(version = "1.0.0")
private PermissionMgrApi permissionMgrApi;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User userByName = userMgrApi.selectOne(s);
if (null == userByName) {
return null;
}
List grantedAuthorities = Lists.newArrayList();
List permissions = permissionMgrApi.selectListByUserId(userByName.getId());
permissions.forEach(permission -> {
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getEnname());
grantedAuthorities.add(grantedAuthority);
});
return new org.springframework.security.core.userdetails.User(userByName.getUsername(),
userByName.getPassword(), grantedAuthorities);
}
}
用戶信息是基于RBAC授權模型,通過username查詢用戶,查到用戶之后通過userId查詢對應的權限,都是很簡單的dao操作,使用mybatis(plus)就可以完成。
復制代碼
3. oAuth2對外提供rest接口,/user/login
oAuth2密碼需要傳username、password、grant_type、client_id、client_secret五個參數,而用戶只需要傳username和password即可,所以其余的參數需要登錄服務自己傳過去。
這里使用RestTemplate,向oAuth2服務發起請求。
成功認證之后,會得到Token。
@PostMapping("/user/login")
public CommonsResponse login(@RequestBody LoginParam loginParam) {
String tokenUrl = "http://localhost:8091/oauth/token";
MultiValueMap multiValueMap = new LinkedMultiValueMap<>();
multiValueMap.add("username", loginParam.getUsername());
multiValueMap.add("password", loginParam.getPassword());
multiValueMap.add("grant_type", oauth2_grant_type);
multiValueMap.add("client_id", oauth2_client_id);
multiValueMap.add("client_secret", oauth2_client_secret);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity> entity = new HttpEntity<>(multiValueMap, headers);
TokenEntity tokenEntity;
try {
tokenEntity = restTemplate.postForObject(tokenUrl, entity, TokenEntity.class);
} catch (Exception e) {
tokenEntity = null;
}
if (null == tokenEntity) {
return new CommonsResponse(BaseStatusEnum.UNAUTHORIZED.getIndex(),
BaseStatusEnum.UNAUTHORIZED.getMsg(), null);
}
return new CommonsResponse(BaseStatusEnum.SUCCESS.getIndex(), BaseStatusEnum.SUCCESS.getMsg(),
tokenEntity);
}
復制代碼
4. 加入網關Gateway
網關可以限流和熔斷,為應用提供統一的入口。這里只使用了基本的功能。
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
# 設置與服務注冊發現組件結合,這樣可以采用服務名的路由策略
discovery:
locator:
enable: true
routes:
- id: BUSINESS-OAUTH2
# 采用LoadBalanceClient方式請求,以lb://開頭,后面跟注冊在nacos上的服務名
uri: lb://business-security
# 斷言,或者叫謂詞
predicates:
- Path=/api/user/**
filters:
- StripPrefix=1
復制代碼
5. 運行示例
5.1 注冊到Nacos:
5.2 訪問網關:
5.3 測試token權限
可以看到在資源服務中配置了
.antMatchers("/user/info").hasAnyAuthority("UserInfo"),即訪問/user/info需要UserInfo權限,而此時RBAC表中,"user"用戶具有這個權限
所以可以訪問成功
此時如果我把"user"用戶的/user/logout權限去掉(對應的表是tb_role_permission),那么他訪問這個url的時候就會返回沒有權限:
(好像是,修改了權限,之前獲取的token就會失效,需要重新獲取)
總結
以上是生活随笔為你收集整理的nacos oaut服务地址_用户认证的例子:Spring Security oAuth2 + Spring Cloud Gateway + Nacos + Dubbo...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c++大作业迷宫游戏 规定时间内完成_小
- 下一篇: 交互式电子杂志_交互环境中电子杂志的生存