マイクロ春のセッション&春のセキュリティサービスのアクセス制御に基づいてマイクロストリーキングサービスを、聞かせてはいけません

マイクロサービスアーキテクチャ

  • ゲートウェイ:指定されたサービスへのルートユーザ要求を、遠位端に含まれるクッキーセッション情報を転送します。
  • ユーザーサービス:ユーザーのログイン認証(認証)、ユーザ認証(認証局)、ユーザー管理(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とユーザーの権限(当局に)キャッシュすること。CustomAuthenticationFilterattemptAuthentication()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()方法することができ、即効性を持ちます。

©著者によって予約の著作権を、著者やコンテンツパートナーに連絡してください再版

IMG

春クラウドゲートウェイ-クイックスタート

周りを探しAPMツールとSkyWalkingは私の本当の愛で見つかりました

春の外部構成は、静的変数のブートアプリケーションの内部に注入します

PDF新しい姿勢にHTML

UnixSocketを使用してJavaドッカーAPIコール

FASTJSON致命的な欠陥

サービスメッシュ- GRPCローカルFBIリモートサービス

使用ThymeleafダイナミックHTMLレンダリング

FASTJSON致命的な欠陥

Spring統合は、ブートをlog4j2日志框架2

コアのJava章では、回答に面接のポイントの要約をオフに設定し、

Javaのインタビューのクリアランスのためのフレームワークの基準点の設定の論文は、答えをまとめています

春のセキュリティ戦闘ドライ品:ユーザーのパスワードを保護する方法

春ブーツのRabbitMQ -プライオリティキュー

オリジナルリンクします。https://mp.weixin.qq.com/s __biz = MzU0MDEwMjgwNA ==&ミッド= 2247486167&IDX = 2&SN = 76dba01d16b7147c9b1dfb7cbf2d8d28&chksm = fb3f132ccc489a3ad2ea05314823d660c40e8af90dcd35800422899958f98b4a258d23badba8&トークン= 280305379&LANG = zh_CNに#RDの?

ブログ記事複数のプラットフォームからこの記事OpenWriteリリース!

おすすめ

転載: www.cnblogs.com/springforall/p/11762374.html