最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

微服務Redis-Session共享登錄狀態(tài)的過程詳解

 更新時間:2023年12月18日 09:24:37   作者:無敵小田田  
這篇文章主要介紹了微服務Redis-Session共享登錄狀態(tài),本文采取Spring security做登錄校驗,用redis做session共享,實現(xiàn)單服務登錄可靠性,微服務之間調(diào)用的可靠性與通用性,需要的朋友可以參考下

一、背景

        隨著項目越來越大,需要將多個服務拆分成微服務,使代碼看起來不要過于臃腫,龐大。微服務之間通常采取feign交互,為了保證不同微服務之間增加授權(quán)校驗,需要增加Spring Security登錄驗證,為了多個服務之間session可以共享,可以通過數(shù)據(jù)庫實現(xiàn)session共享,也可以采用redis-session實現(xiàn)共享。

        本文采取Spring security做登錄校驗,用redis做session共享。實現(xiàn)單服務登錄可靠性,微服務之間調(diào)用的可靠性與通用性

二、代碼

本文項目采取 主服務一服務、子服務二 來舉例

1、服務依賴文件

主服務依賴

    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis', version: '2.5.4'
    implementation group: 'org.springframework.session', name: 'spring-session-data-redis', version: '2.4.1'
    implementation(group: 'io.github.openfeign', name: 'feign-httpclient')
    implementation 'org.springframework.boot:spring-boot-starter-security'

子服務依賴

    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis', version: '2.5.4'
    implementation group: 'org.springframework.session', name: 'spring-session-data-redis', version: '2.4.1'
    implementation 'org.springframework.boot:spring-boot-starter-security'

2、服務配置文件

主服務配置文件

#redis連接

spring.redis.host=1.2.3.4

#Redis服務器連接端口

spring.redis.port=6379

#Redis服務器連接密碼

spring.redis.password=password

#連接池最大連接數(shù)(使用負值表示沒有限制)

spring.redis.pool.max-active=8

#連接池最大阻塞等待時間(使用負值表示沒有限制)

spring.redis.pool.max-wait=-1

#連接池中的最大空閑連接

spring.redis.pool.max-idle=8

#連接池中的最小空閑連接

spring.redis.pool.min-idle=0

#連接超時時間(毫秒)

spring.redis.timeout=30000

#數(shù)據(jù)庫

spring.redis.database=0

#redis-session配置

spring.session.store-type=redis

#部分post請求過長會報錯,需加配置

server.tomcat.max-http-header-size=65536

子服務配置文件

#單獨登錄秘鑰

micService.username=service

micService.password=aaaaaaaaaaaaa

#登錄白名單

micService.ipList=1.2.3.4,1.2.3.5,127.0.0.1,0:0:0:0:0:0:0:1

spring.redis.host=1.2.3.4

#Redis服務器連接端口

spring.redis.port=6379

#Redis服務器連接密碼

spring.redis.password=password

#連接池最大連接數(shù)(使用負值表示沒有限制)

spring.redis.pool.max-active=8

#連接池最大阻塞等待時間(使用負值表示沒有限制)

spring.redis.pool.max-wait=-1

#連接池中的最大空閑連接

spring.redis.pool.max-idle=8

#連接池中的最小空閑連接

spring.redis.pool.min-idle=0

#連接超時時間(毫秒)

spring.redis.timeout=30000

#數(shù)據(jù)庫

spring.redis.database=0

#最大請求頭限制

server.maxPostSize=-1

server.maxHttpHeaderSize=102400

#redis session緩存

spring.session.store-type=redis

server.servlet.session.timeout=30m

3、登錄校驗文件

主服務SecurityConfig.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //注入密碼加密的類
    @Bean
    public AuthenticationProvider authenticationProvider() {
        AuthenticationProvider authenticationProvider = new EncoderProvider();
        return authenticationProvider;
    }
    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
        auth.authenticationProvider(authenticationProvider());
    }
    public static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .successHandler((request,response,authentication) -> {
                    HttpSession session = request.getSession();
                    session.setAttribute("TaobaoUser",authentication.getPrincipal());
                    ObjectMapper mapper = new ObjectMapper();
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    TaobaoUser user = (CurrentUser)session.getAttribute("TaobaoUser");
                    out.write(mapper.writeValueAsString(user));
                    out.flush();
                    out.close();
                })
                .failureHandler((request,response,authentication) -> {
                    ObjectMapper mapper = new ObjectMapper();
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    out.write(mapper.writeValueAsString(new ExceptionMessage("400",authentication.getMessage())));
                    out.flush();
                    out.close();
                })
                .loginPage("/Login.html")
                .loginProcessingUrl("/login")
                .and()
                .authorizeRequests()
                .antMatchers("/api/common/invalidUrl","/**/*.css", "/**/*.js", "/**/*.gif ", "/**/*.png ", "/**/*.jpg", "/webjars/**", "**/favicon.ico", "/guestAccess", "/Login.html",
                        "/v2/api-docs","/configuration/security","/configuration/ui","/api/common/CheckLatestVersionInfo").permitAll()
                .anyRequest()
                //任何請求
                .authenticated()
                .and()
                .sessionManagement()
                .maximumSessions(-1)
                .sessionRegistry(sessionRegistry());
        ;
        http.csrf().disable();
    }
    @Autowired
    private FindByIndexNameSessionRepository sessionRepository;
    @Bean
    public SpringSessionBackedSessionRegistry sessionRegistry(){
        return new SpringSessionBackedSessionRegistry(sessionRepository);
    }
}

EncoderProvider.java

@Service
public class EncoderProvider implements AuthenticationProvider {
    public static final Logger logger = LoggerFactory.getLogger(EncoderProvider.class);
    /**
     * 自定義驗證方式
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        try {
            //支持用戶名和員工號登錄 可能為用戶名或員工號
            String username = authentication.getName();
            String credential = (String) authentication.getCredentials();
            //加密過程在這里體現(xiàn)
            TaobaoUser user= userService.getUserData(username);
            //校驗,用戶名是否存在
            if(user==null){
                throw new DisabledException("用戶名或密碼錯誤");
            }
            //校驗登錄狀態(tài)
            checkPassword()
            Collection<GrantedAuthority> authorities = new ArrayList<>();
            return new UsernamePasswordAuthenticationToken(userCurrent, credential, authorities);
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new DisabledException("登錄發(fā)生錯誤 : " + ex.getMessage());
        }
    }
    @Override
    public boolean supports(Class<?> arg0) {
        return true;
    }

子服務SecurityConfig.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //注入密碼加密的類
    @Bean
    public AuthenticationProvider authenticationProvider() {
        AuthenticationProvider authenticationProvider = new EncoderProvider();
        return authenticationProvider;
    }
    @Autowired
    public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProvider());
    }
    public static final Logger logger = LoggerFactory.getLogger(SecurityConfig.class);
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        logger.info("用戶登錄日志test1 username:"+http.toString());
                http.formLogin()
                    .loginProcessingUrl("/login")
                    .successHandler((request,response,authentication) -> {
                    HttpSession session = request.getSession();
                    session.setAttribute("TaobaoUser",authentication.getPrincipal());
                    ObjectMapper mapper = new ObjectMapper();
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    TaobaoUser user = (TaobaoUser )session.getAttribute("TaobaoUser");
                    out.write(mapper.writeValueAsString(user));
                    out.flush();
                    out.close();
                })
                .failureHandler((request,response,authentication) -> {
                    ObjectMapper mapper = new ObjectMapper();
                    response.setContentType("application/json;charset=utf-8");
                    PrintWriter out = response.getWriter();
                    out.write(mapper.writeValueAsString(new ExceptionMessage("400",authentication.getMessage())));
                    out.flush();
                    out.close();
                })
                .loginPage("/Login.html")
                .and()
                .authorizeRequests()
                .antMatchers("/**/*.css", "/**/*.js", "/**/*.gif ", "/**/*.png ",
                        "/**/*.jpg", "/webjars/**", "**/favicon.ico", "/Login.html",
                        "/v2/api-docs","/configuration/security","/configuration/ui").permitAll()
                .anyRequest().authenticated()
                .and()
                .sessionManagement()
                .maximumSessions(-1)
                .sessionRegistry(sessionRegistry());
        http.csrf().disable();
    }
    @Autowired
    private FindByIndexNameSessionRepository sessionRepository;
    @Bean
    public SpringSessionBackedSessionRegistry sessionRegistry(){
        return new SpringSessionBackedSessionRegistry(sessionRepository);
    }
}

EncoderProvider.java

@Service
public class EncoderProvider implements AuthenticationProvider {
    public static final Logger logger = LoggerFactory.getLogger(EncoderProvider.class);
    @Value("${service.username}")
    private String  userName1;
    @Value("${service.ipList}")
    private String  ipList;
    /**
     * 自定義驗證方式
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        try {
            //支持用戶名和員工號登錄 可能為用戶名或員工號
            String username = authentication.getName();
            String credential = (String)authentication.getCredentials();
            TaobaoUser user=new TaobaoUser();
            if(username.equals(userName1)){
                  List<String> ips = Arrays.asList(ipList.split(","));
                  WebAuthenticationDetails details = (WebAuthenticationDetails) authentication.getDetails();
                  String remoteIp = details.getRemoteAddress();
                  logger.info("ip為{}-通過用戶{}調(diào)用接口",remoteIp,username);
                  if(!ips.contains(remoteIp)){
                      throw new DisabledException("無權(quán)登陸!");
                  }
            }else{
                throw new DisabledException("賬戶不存在!");
            }
            user.setA("A");
            Collection<GrantedAuthority> authorities = new ArrayList<>();
            return new UsernamePasswordAuthenticationToken(currentUser, credential, authorities);
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new DisabledException("登錄發(fā)生錯誤 : " + ex.getMessage());
        }
    }
    @Override
    public boolean supports(Class<?> arg0) {
        return true;
    }
}

4、主服務feign配置

FeignManage.java

#url = "${file.client.url}",
@FeignClient(name="file-service",
            fallback = FeignFileManageFallback.class,
            configuration = FeignConfiguration.class)
public interface FeignFileManage {
    @RequestMapping(value = "/file/upload", method = {RequestMethod.POST}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    ApiBaseMessage fileUpload(@RequestPart("file") MultipartFile file, @RequestParam("fileName") String fileName) ;
}
public class FeignManageFallback implements FeignManage{
    @Override
    public ApiBaseMessage fileUpload(MultipartFile file, String type) {
        return ApiBaseMessage.getOperationSucceedInstance("400","失敗");
    }
}

FeignFileManageFallback.java

FeignConfiguration.java

@Configuration
@Import(FeignClientsConfiguration.class)
public class FeignConfiguration {
    /**
      刪除請求頭文件
     */
    final String[] copyHeaders = new String[]{"transfer-encoding","Content-Length"};
    @Bean
    public FeignFileManageFallback echoServiceFallback(){
        return new FeignFileManageFallback();
    }
    @Bean
    public FeignBasicAuthRequestInterceptor getFeignBasicAuthRequestInterceptor(){
        return new FeignBasicAuthRequestInterceptor();
    }
    /**
     *    feign 調(diào)用,添加CurrentUser
     */
    private class FeignBasicAuthRequestInterceptor implements RequestInterceptor {
        @Override
        public void apply(RequestTemplate template) {
            //1、使用RequestContextHolder拿到剛進來的請求數(shù)據(jù)
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (requestAttributes != null) {
                HttpServletRequest request = requestAttributes.getRequest();
                Enumeration<String> headerNames = request.getHeaderNames();
                if (headerNames != null) {
                    while (headerNames.hasMoreElements()) {
                        String name = headerNames.nextElement();
                        String values = request.getHeader(name);
                        //刪除的請求頭
                        if (!Arrays.asList(copyHeaders).contains(name)) {
                            template.header(name, values);
                        }
                    }
                }
            }else{
                template.header("Accept", "*/*");
                template.header("Accept-Encoding", "gzip, deflate, br");
                template.header("Content-Type", "application/json");
            }
            //增加用戶信息
            if(requestAttributes!=null && SessionHelper.getCurrentUser()!=null){
                try {
                    template.header("TaobaoUser", URLEncoder.encode(JSON.toJSONString(SessionHelper.getCurrentUser()),"utf-8") );
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

5、主服務session文件

SessionUtil.java

 
public class SessionUtil {
    public static CurrentUser getCurrentUser() {
        HttpSession session = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession();
        CurrentUser user = (CurrentUser)session.getAttribute("TaobaoUser");
        return user;
    }
    public static void setCurrentUser(String userName){
        HttpSession session = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession();
        Collection<GrantedAuthority> authorities = new ArrayList<>();
        session.setAttribute("TaobaoUser",new CurrentUser(userName, "", authorities));
    }
}

三、完成配置后

1、直接訪問主服務接口,不登錄無法訪問

2、直接訪問自服務,不登錄無法訪問,(可通過nacos配置用戶密碼實現(xiàn)登錄)

3、主服務通過feign調(diào)用子服務接口正常(session已共享)

4、子服務登陸之后,調(diào)用主服務理論也可以,需校驗下主服務用戶側(cè)

到此這篇關(guān)于微服務Redis-Session共享登錄狀態(tài)的文章就介紹到這了,更多相關(guān)Redis Session共享登錄狀態(tài)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 探索Java I/O 模型的演進

    探索Java I/O 模型的演進

    什么是同步?什么是異步?阻塞和非阻塞又有什么區(qū)別?本文先從 Unix 的 I/O 模型講起,介紹了5種常見的 I/O 模型。而后再引出 Java 的 I/O 模型的演進過程,并用實例說明如何選擇合適的 Java I/O 模型來提高系統(tǒng)的并發(fā)量和可用性。,需要的朋友可以參考下
    2019-06-06
  • Springboot攔截器如何獲取@RequestBody參數(shù)

    Springboot攔截器如何獲取@RequestBody參數(shù)

    這篇文章主要介紹了Springboot攔截器如何獲取@RequestBody參數(shù)的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • SpringBoot整合Spring?Security實現(xiàn)權(quán)限控制的全過程

    SpringBoot整合Spring?Security實現(xiàn)權(quán)限控制的全過程

    本文介紹了在企業(yè)級項目中使用SpringSecurity實現(xiàn)權(quán)限控制的方法,包括認證與授權(quán)的概念、核心數(shù)據(jù)模型、SpringSecurity入門搭建、核心配置、數(shù)據(jù)庫認證與密碼加密、權(quán)限控制方式、用戶退出登錄配置等,最后,強調(diào)了生產(chǎn)環(huán)境下的安全配置要求,需要的朋友可以參考下
    2026-04-04
  • Java調(diào)用通義千問API的詳細步驟

    Java調(diào)用通義千問API的詳細步驟

    這篇文章主要介紹了在Java中接入通義千問API的步驟,包括獲取APIKey、添加依賴、配置模型和流式響應等,并提供了響應處理和高級功能實現(xiàn)示例,以及常見問題解決方案,需要的朋友可以參考下
    2026-03-03
  • javaWeb傳收參數(shù)方式總結(jié)示例分析

    javaWeb傳收參數(shù)方式總結(jié)示例分析

    這篇文章主要為大家介紹了javaWeb傳收參數(shù)方式總結(jié)示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-08-08
  • SpringBoot基于配置實現(xiàn)短信服務策略的動態(tài)切換

    SpringBoot基于配置實現(xiàn)短信服務策略的動態(tài)切換

    這篇文章主要為大家詳細介紹了SpringBoot在接入多個短信服務商(如阿里云、騰訊云、華為云)后,如何根據(jù)配置或環(huán)境切換使用不同的服務商,需要的小伙伴可以了解下
    2025-04-04
  • 利用反射實現(xiàn)Excel和CSV 轉(zhuǎn)換為Java對象功能

    利用反射實現(xiàn)Excel和CSV 轉(zhuǎn)換為Java對象功能

    將Excel或CSV文件轉(zhuǎn)換為Java對象(POJO)以及將Java對象轉(zhuǎn)換為Excel或CSV文件可能是一個復雜的過程,但如果使用正確的工具和技術(shù),這個過程就會變得十分簡單,在本文中,我們將了解如何利用一個Java反射的庫來實現(xiàn)這個功能,需要的朋友可以參考下
    2023-11-11
  • JAVA實現(xiàn)RSA簽名、驗簽全過程

    JAVA實現(xiàn)RSA簽名、驗簽全過程

    文章介紹了如何使用Java實現(xiàn)RSA簽名和驗簽,以確保數(shù)據(jù)傳輸?shù)陌踩?包括生成公私鑰對、使用私鑰簽名和公鑰驗簽的流程,提供了三個工具類:Rsa.java、Base64.java和BaseHelper.java,示例展示了如何將業(yè)務參數(shù)排序并生成簽名,以及如何驗證接收到的參數(shù)簽名
    2025-10-10
  • SpringAOP事務配置語法及實現(xiàn)過程詳解

    SpringAOP事務配置語法及實現(xiàn)過程詳解

    這篇文章主要介紹了SpringAOP事務配置語法及實現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • 深入理解Java設計模式之原型模式

    深入理解Java設計模式之原型模式

    這篇文章主要介紹了JAVA設計模式之原型模式的的相關(guān)資料,文中示例代碼非常詳細,供大家參考和學習,感興趣的朋友可以了解下
    2021-11-11

最新評論

华宁县| 永春县| 永新县| 嘉义市| 宁安市| 海安县| 荥阳市| 谢通门县| 蓝山县| 勐海县| 天柱县| 东平县| 连州市| 易门县| 彭泽县| 永新县| 晴隆县| 海林市| 琼结县| 简阳市| 故城县| 吉隆县| 永州市| 隆昌县| 玛曲县| 昆明市| 天水市| 杭州市| 玉环县| 章丘市| 凤庆县| 望谟县| 贵阳市| 类乌齐县| 道真| 枣阳市| 云林县| 禹州市| 永川市| 永仁县| 石首市|