Spring SessionとSpring securityを使ってサイトのログイン改造を完了!!

7994 ワード

前回黒さんは、Webアプリケーションが再起動したり拡張したりしても、Sessionが失われるリスクがないように、4つの分散型コンシステンシSessionの実装方法を紹介しました.
今日では,この方式を用いてSessionストレージ方式を改造し,Redisに統合して格納する.実装シナリオ
まず、フレームワークに頼らなければ、バックエンドSession集中ストレージをどのように実現するかを考えてみましょう.
ここでは、トップページが直接アクセスできるなど、一部のページを除いて、他のページにはログインしてからアクセスする必要があると仮定します.
このニーズを実現する必要がある場合は、各リクエストに対して認証を行う必要があります.認証の目的は、ユーザーがログインしているかどうかを判断し、ユーザーロールを判断することです.
ユーザーがログインしていない場合は、ログインページに強制的にジャンプしてログインする必要があります.
ユーザがログインした後,ログインして取得したユーザ情報をセッションに格納する必要があり,後で認証を要求するにはセッションに存在するか否かを判断するだけでよい.
プロセス全体を知ってから、原理を実現するのは難しくありません.
AOPのような原理を用いて,各リクエストが入ってきた後,セッションにユーザ情報が存在するか否かを判断し,存在しない場合はログインページにジャンプすることができる.
プロセス全体は次のとおりです.
サーブレットFilterを利用して上記のプロセスを実現することができますが、上記のプロセス全体、Springはすでに実現してくれているので、車輪を繰り返す必要はありません.
Spring-SessionとSpring-securityを使用して、上記のWebサイトのプロセスを実現できます.
Spring-SessionはSpringがユーザーSessionを管理する一連の実装スキームを提供し、Spring-Sessionを使用すると、TomcatなどのデフォルトのWEBコンテナで生成されたSessionがSpring-Sessionに引き継がれる.
このほか、Spring-Sessionでは、Redis、データベースなど、いくつかの一般的なバックエンドストレージ実装スキームも提供されています.
Spring-Sessionがあれば、Sessionバックエンド集中ストレージを解決してくれるだけです.しかし、上記のプロセスでは、Spring-securityを使用して実現できるログイン権限が必要です.
Spring-securityは、統合されたログイン認証方式を維持し、Spring-Sessionと組み合わせて使用できます.ユーザーがログインした後、取得したユーザー情報はSpring-Sessionに自動的に格納されます.
はい、くだらないことを言わないで、実装コードを見てみましょう.
     Spring Boot   , Spring-Boot    :2.3.2.RELEASE

Spring Session
まずSpring Session依存を導入し,ここではRedis集中を用いてSession情報を格納するので,以下の依存が必要である.org.springframework.session spring-session-data-redis
Spring Bootプロジェクトでない場合は、org.springframework.data spring-data-redis 2.3.0.RELEASE org.springframework.session spring-session-core 2.3.0.RELEASE
依存を導入した後、まずアプリケーションが必要です.propertiesはセッション関連の構成を追加します.
Sessionストレージ方式
spring.session.store-type=redis
セッションの有効期限、デフォルト単位はs
server.servlet.session.timeout=600
セッションがRedisキーに格納するプレフィックス
spring.session.redis.namespace=test:spring:session
Redis関連構成
spring.redis.host=127.0.0.1 spring.redis.password=**** spring.redis.port=6379
構成が完了すると、Spring SessionはSession情報の管理を開始します.次に、テストします.
@ResponseBody @GetMapping("/hello") public String hello() { return “Hello World”; }
上記のアドレスにアクセスした後、Redisにアクセスすると、格納されたSession情報が表示されます.
       Redis    「Another Redis DeskTop Manager」,      UI       ,      ,    :

https://github.com/qishibo/anotherredisdesktopmanager/releases

デフォルトでは、SessionのデフォルトではHttpSessionシーケンス化が使用されます.この値は直感的ではありません.これをjsonシーケンス化方式に変更してredisに格納することができる.
@Configuration public class HttpSessionConfig implements BeanClassLoaderAware {
private ClassLoader loader;

@Bean
public RedisSerializer springSessionDefaultRedisSerializer() {
    return new GenericJackson2JsonRedisSerializer(objectMapper());
}

/**
 * Customized {@link ObjectMapper} to add mix-in for class that doesn't have default
 * constructors
 *
 * @return the {@link ObjectMapper} to use
 */
private ObjectMapper objectMapper() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModules(SecurityJackson2Modules.getModules(this.loader));
    return mapper;
}


@Override
public void setBeanClassLoader(ClassLoader classLoader) {
    this.loader = classLoader;
}

} http://v.qq.com/x/search/?q=%E5%8D%8E%E7%BA%B3%E5%8E%85%E5%BC%80%E6%88%B7_%E6%80%BB%E5%8F%B018183615678 修正後のRedisキーの値は次のとおりです.
ps:   Redis     ,         ,    。

Spring Sessionには@EnableRedisHttpSessionも存在し、この注記でSpring Session関連構成を構成することができます.
@EnableRedisHttpSession(redisNamespace = “test:session”)
この注釈を使用するとアプリケーションが発生することに注意してください.properties Session関連構成は無効です.つまりSpring Sessionは注釈上の構成を直接使用します.
ここで黒さんはプロファイルの使い方をお勧めします.
さあ、Spring Sessionはここでアクセスが完了しました.Spring security
Spring Sessionを統合し、Session統合Redisストレージを完了しました.次に,主に要求されたログイン認証を実現する必要がある.
このステップではSpring securityを使用して統一的な上陸認証サービスを実現し、同じフレームワークのShiroもあります.ここではSpringファミリーバケツを使用します.
まず依存する必要がある依存:org.springframework.boot spring-boot-starter-security
上記の依存を導入すると、アプリケーションが起動するとランダムなパスワードが生成され、すべてのリクエストがSpring securityのページにジャンプします.
デフォルトのパスワード
ログインページ
ここでは、自分のビジネスのログインページを実現する必要があります.そのため、ログイン検証ロジックをカスタマイズする必要があります.
Spring securityでは、UserDetailsServiceインタフェースを実装し、loadUserByUsernameメソッドロジックを書き換えるだけです.
@Service public class UserServiceImpl implements UserDetailsService {
@Autowired
PasswordEncoder passwordEncoder;


@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

    //     ,      
    String uname = "admin";
    String passwd = "1234qwer";

    //        ,            ,     ,    :
    // User user = userDAO.query(username);

    if (!username.equals(uname)) {
        throw new UsernameNotFoundException(username);
    }
    //     Spring security     User   
    return User.builder()
            .username(username)
            .passwordEncoder(s -> passwordEncoder.encode(passwd))
            .authorities(new SimpleGrantedAuthority("user"))
            .build();
}

}
上記のコードは実装されています.ここでは主にメモリの固定ユーザー名とパスワード、実際の環境では、データベースからユーザー情報をクエリーするように変更する必要があります.
次に、UserServiceImplをSpring securityに構成する必要があります.
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserServiceImpl userService;

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

/**
 *                
 *
 * @param auth
 * @throws Exception
 */
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    //               userService
    //                      
    auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
}

}
上記の構成では,暗号部分はBCryptアルゴリズムを用いて暗号化しているが,ここでは暗号化と復号化は同じ方式を用いる必要があることに注意する必要がある.
次に、spring-session-data-redisページを直接使用するのがおっくうなカスタムログインページを実現する必要があります.Login
Please Login -
Invalid username and password.
You have been logged out.
Username Password remember me:
Log in
ここで注意したいのは、formフォームのリクエストアドレスは/auth/loginを使用し、以下の構成で変更する必要があります.デフォルトでは、ログインリクエストのアドレスは/loginが必要です.
次に、上記のSecurityConfigクラスに対応する構成方法を追加します.
/**
  • カスタム処理登録処理

  • @param http
  • @throws Exception*/@Override protected void configure(HttpSecurity http)throws Exception{http.authorizeRequests((authorize)-->authorize.requestMatchers(PathRequest.toStaticResources(..atCommonLocations().permitAll()/静的リソース(例えばcss、jsはログイン認証を必要としない.anyRequest(..anyRequest(..permitAll()(....permitAll(()).permitAll((()/)/静的リソース(例えばcss、jsは登録認証を必要としない.anyRequest(.//その他のページはログイン認証が必要).formLogin((formLogin)->formLogin//カスタムログインページ.loginPage(「/login」)/ログインページ.loginProcessingUrl(「/auth/login」)/カスタムログイン要求アドレス.permitAll()/ログインページはもちろん認証する必要はありません.そうしないと子供になりませんか?).logout(LogoutConfigurer::permitAll//登録ページ).rememberMe(rememberMe->rememberMe.rememberMeCookieName("test-remember")/カスタム記憶私cookie名.key("test")/塩値.tokenValiditySeconds(3600*12)//記憶私、ローカル生成cookieはユーザー情報を含む;}

  • この方法は長いかもしれませんが、重点的に説明します.
    authorizeRequests               ,                ,             
    formLogin               ,         。
    logout               。
    rememberMe        ,    Session     ,               Cookie           。
    

    最後に、ページのジャンプアドレスを設定する必要があります.
    @Configuration public class WebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //   
        registry.addViewController("/").setViewName("home");
        //         home  
        registry.addViewController("/login").setViewName("login");
    }
    

    }
    まとめ
    ここまでSpring-SessionとSpring-securityを統合し、完全なWebサイトのログイン認証機能を完了しました.この例から,この2つのフレームワークを導入した後,Spring仕様に従って開発すればよいだけで,他の複雑な実現原理は自分で実現する必要がなく,本当に便利であることがわかる.
    上はただ1つの簡単な例で、黒はただ玉を投げて、実際の開発の中で配置を修正する必要があるかもしれませんが、ここでは小さなパートナーを使って自分で深く研究する必要があります.