マイクロサービスアーキテクチャ
- ゲートウェイ:指定されたサービスへのルートユーザ要求を、遠位端に含まれるクッキーセッション情報を転送します。
- ユーザーサービス:ユーザーのログイン認証(認証)、ユーザ認証(認証局)、ユーザー管理(Redisのセッション管理)
- その他のサービス:ユーザ依存の情報Redisの要求の検証インタフェース
ユーザ - ロール - 許可テーブルの構造設計
- 許可テーブルの
許可テーブルは、ユーザ管理、リソース管理、構成例をテーブルとして最小粒径の個々の機能を制御します。
ID | 権限 | 説明 |
---|---|---|
1 | ROLE_ADMIN_USER | すべてのユーザーを管理します |
2 | ROLE_ADMIN_RESOURCE | すべてのリソースの管理 |
3 | ROLE_A_1 | サービスAのインタフェースへのアクセス |
4 | ROLE_A_2 | インターフェース・サービスAへのアクセスのもう一つの特権 |
5 | ROLE_B_1 | 特定のインターフェイスにServiceBアクセス |
6 | ROLE_B_2 | インタフェースServiceBへのアクセスのもう一つの特権 |
- 役割-権限テーブルの
カスタムロールは、そのようなスーパー管理者としての権利の様々な組み合わせは、すべての権利、テーブル構造の例があります。
ID | 名前 | authority_ids |
---|---|---|
1 | スーパー管理者 | 1,2,3,4,5,6 |
2 | 管理者 | 3,4 |
3 | 管理者B | 5,6 |
4 | 普通のユーザー | ヌル |
- ユーザ-ロールテーブル
ユーザーは、1つ以上のロールに結合している、すなわち、様々な権利を割り当てる、例示的なテーブル構造:
ユーザーID | ROLE_ID |
---|---|
1 | 1 |
1 | 4 |
2 | 2 |
ユーザーサービスデザイン
Mavenの依存関係(すべてのサービス)
<!-- Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- Spring Session Redis -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
アプリケーション構成のapplication.yml
一例:
# Spring Session 配置
spring.session.store-type=redis
server.servlet.session.persistent=true
server.servlet.session.timeout=7d
server.servlet.session.cookie.max-age=7d
# Redis 配置
spring.redis.host=<redis-host>
spring.redis.port=6379
# MySQL 配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://<mysql-host>:3306/test
spring.datasource.username=<username>
spring.datasource.password=<passowrd>
ユーザーのログイン認証(認証)と承認(権限)
Slf4j
public class CustomAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private final UserService userService;
CustomAuthenticationFilter(String defaultFilterProcessesUrl, UserService userService) {
super(new AntPathRequestMatcher(defaultFilterProcessesUrl, HttpMethod.POST.name()));
this.userService = userService;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
JSONObject requestBody = getRequestBody(request);
String username = requestBody.getString("username");
String password = requestBody.getString("password");
UserDO user = userService.getByUsername(username);
if (user != null && validateUsernameAndPassword(username, password, user)){
// 查询用户的 authority
List<SimpleGrantedAuthority> userAuthorities = userService.getSimpleGrantedAuthority(user.getId());
return new UsernamePasswordAuthenticationToken(user.getId(), null, userAuthorities);
}
throw new AuthenticationServiceException("登录失败");
}
/**
* 获取请求体
*/
private JSONObject getRequestBody(HttpServletRequest request) throws AuthenticationException{
try {
StringBuilder stringBuilder = new StringBuilder();
InputStream inputStream = request.getInputStream();
byte[] bs = new byte[StreamUtils.BUFFER_SIZE];
int len;
while ((len = inputStream.read(bs)) != -1) {
stringBuilder.append(new String(bs, 0, len));
}
return JSON.parseObject(stringBuilder.toString());
} catch (IOException e) {
log.error("get request body error.");
}
throw new AuthenticationServiceException(HttpRequestStatusEnum.INVALID_REQUEST.getMessage());
}
/**
* 校验用户名和密码
*/
private boolean validateUsernameAndPassword(String username, String password, UserDO user) throws AuthenticationException {
return username == user.getUsername() && password == user.getPassword();
}
}
@EnableWebSecurity
@AllArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final String LOGIN_URL = "/user/login";
private static final String LOGOUT_URL = "/user/logout";
private final UserService userService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(LOGIN_URL).permitAll()
.anyRequest().authenticated()
.and()
.logout().logoutUrl(LOGOUT_URL).clearAuthentication(true).permitAll()
.and()
.csrf().disable();
http.addFilterAt(bipAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.rememberMe().alwaysRemember(true);
}
/**
* 自定义认证过滤器
*/
private CustomAuthenticationFilter customAuthenticationFilter() {
CustomAuthenticationFilter authenticationFilter = new CustomAuthenticationFilter(LOGIN_URL, userService);
return authenticationFilter;
}
}
その他のデザインサービス
アプリケーション構成のapplication.yml
一例:
# Spring Session 配置
spring.session.store-type=redis
# Redis 配置
spring.redis.host=<redis-host>
spring.redis.port=6379
グローバルセキュリティ設定
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.csrf().disable();
}
}
ユーザー認証情報取得
ユーザーによる成功したログインユーザサービスの後、ユーザー情報はRedisの、キャッシュされた情報にキャッシュされ、この方法は、それがあるとして、返されたオブジェクトは、関連オブジェクトを返すのRedisは、ユーザーのIDとユーザーの権限(当局に)キャッシュすること。CustomAuthenticationFilter
attemptAuthentication()
new UsernamePasswordAuthenticationToken(user.getId(), null, userAuthorities)
UsernamePasswordAuthenticationToken
コンストラクタの最初の引数は、オブジェクトがカスタムキャッシュすることができ、Objectオブジェクトです。
次のようにマイクロモジュール内のユーザサービスの情報を取得します。
@GetMapping()
public WebResponse test(@AuthenticationPrincipal UsernamePasswordAuthenticationToken authenticationToken){
// 略
}
アクセス制御
- 権限を有効にし、アノテーションベースのアプローチ
@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
- 簡単なチェックの権限は
、たとえば、唯一持ってできるように、役割のインターフェイスを削除するROLE_ADMIN_USER
アクセスにユーザー権利を。
/**
* 删除角色
*/
@PostMapping("/delete")
@PreAuthorize("hasRole('ADMIN_USER')")
public WebResponse deleteRole(@RequestBody RoleBean roleBean){
// 略
}
@PreAuthorize("hasRole('<authority>')")
それはマイクロサービスモジュールに作用することができます
- カスタム許可チェックを
上記に示した、hasRole()
埋め込まれている春のセキュリティは、カスタムのためには、式ベースのアクセス制御、例を使用することがあります。
/**
* 自定义校验服务
*/
@Service
public class CustomService{
public boolean check(UsernamePasswordAuthenticationToken authenticationToken, String extraParam){
// 略
}
}
/**
* 删除角色
*/
@PostMapping()
@PreAuthorize("@customService.check(authentication, #userBean.username)")
public WebResponse custom(@RequestBody UserBean userBean){
// 略
}
authentication
ビルトインオブジェクトに属する、#
パラメータの値を取得
- 任意のユーザー権限の動的な変更
、ユーザのアクセス権を変更し、原則として、Redisのユーザーの権限に格納されている情報には、Redisのを操作する必要があります、例:
@Service
@AllArgsConstructor
public class HttpSessionService<S extends Session> {
private final FindByIndexNameSessionRepository<S> sessionRepository;
/**
* 重置用户权限
*/
public void resetAuthorities(Long userId, List<GrantedAuthority> authorities){
UsernamePasswordAuthenticationToken newToken = new UsernamePasswordAuthenticationToken(userId, null, authorities);
Map<String, S> redisSessionMap = sessionRepository.findByPrincipalName(String.valueOf(userId));
redisSessionMap.values().forEach(session -> {
SecurityContextImpl securityContext = session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
securityContext.setAuthentication(newToken);
session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, securityContext);
sessionRepository.save(session);
});
}
}
ユーザー権限を変更し、単に呼び出すhttpSessionService.resetAuthorities()
方法することができ、即効性を持ちます。
©著者によって予約の著作権を、著者やコンテンツパートナーに連絡してください再版
● 周りを探しAPMツールとSkyWalkingは私の本当の愛で見つかりました
● 春の外部構成は、静的変数のブートアプリケーションの内部に注入します
● UnixSocketを使用してJavaドッカーAPIコール
● サービスメッシュ- GRPCローカルFBIリモートサービス
● コアのJava章では、回答に面接のポイントの要約をオフに設定し、
● Javaのインタビューのクリアランスのためのフレームワークの基準点の設定の論文は、答えをまとめています
● 春のセキュリティ戦闘ドライ品:ユーザーのパスワードを保護する方法
オリジナルリンクします。https://mp.weixin.qq.com/s __biz = MzU0MDEwMjgwNA ==&ミッド= 2247486167&IDX = 2&SN = 76dba01d16b7147c9b1dfb7cbf2d8d28&chksm = fb3f132ccc489a3ad2ea05314823d660c40e8af90dcd35800422899958f98b4a258d23badba8&トークン= 280305379&LANG = zh_CNに#RDの?
ブログ記事複数のプラットフォームからこの記事OpenWriteリリース!