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

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

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

一、背景

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

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

二、代碼

本文項(xiàng)目采取 主服務(wù)一服務(wù)、子服務(wù)二 來(lái)舉例

1、服務(wù)依賴文件

主服務(wù)依賴

    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'

子服務(wù)依賴

    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、服務(wù)配置文件

主服務(wù)配置文件

#redis連接

spring.redis.host=1.2.3.4

#Redis服務(wù)器連接端口

spring.redis.port=6379

#Redis服務(wù)器連接密碼

spring.redis.password=password

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

spring.redis.pool.max-active=8

#連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒(méi)有限制)

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

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

spring.redis.pool.max-idle=8

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

spring.redis.pool.min-idle=0

#連接超時(shí)時(shí)間(毫秒)

spring.redis.timeout=30000

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

spring.redis.database=0

#redis-session配置

spring.session.store-type=redis

#部分post請(qǐng)求過(guò)長(zhǎng)會(huì)報(bào)錯(cuò),需加配置

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

子服務(wù)配置文件

#單獨(dú)登錄秘鑰

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服務(wù)器連接端口

spring.redis.port=6379

#Redis服務(wù)器連接密碼

spring.redis.password=password

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

spring.redis.pool.max-active=8

#連接池最大阻塞等待時(shí)間(使用負(fù)值表示沒(méi)有限制)

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

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

spring.redis.pool.max-idle=8

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

spring.redis.pool.min-idle=0

#連接超時(shí)時(shí)間(毫秒)

spring.redis.timeout=30000

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

spring.redis.database=0

#最大請(qǐng)求頭限制

server.maxPostSize=-1

server.maxHttpHeaderSize=102400

#redis session緩存

spring.session.store-type=redis

server.servlet.session.timeout=30m

3、登錄校驗(yàn)文件

主服務(wù)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()
                //任何請(qǐng)求
                .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);
    /**
     * 自定義驗(yàn)證方式
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        try {
            //支持用戶名和員工號(hào)登錄 可能為用戶名或員工號(hào)
            String username = authentication.getName();
            String credential = (String) authentication.getCredentials();
            //加密過(guò)程在這里體現(xiàn)
            TaobaoUser user= userService.getUserData(username);
            //校驗(yàn),用戶名是否存在
            if(user==null){
                throw new DisabledException("用戶名或密碼錯(cuò)誤");
            }
            //校驗(yàn)登錄狀態(tài)
            checkPassword()
            Collection<GrantedAuthority> authorities = new ArrayList<>();
            return new UsernamePasswordAuthenticationToken(userCurrent, credential, authorities);
        } catch (Exception ex) {
            ex.printStackTrace();
            throw new DisabledException("登錄發(fā)生錯(cuò)誤 : " + ex.getMessage());
        }
    }
    @Override
    public boolean supports(Class<?> arg0) {
        return true;
    }

子服務(wù)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;
    /**
     * 自定義驗(yàn)證方式
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        try {
            //支持用戶名和員工號(hào)登錄 可能為用戶名或員工號(hào)
            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為{}-通過(guò)用戶{}調(diào)用接口",remoteIp,username);
                  if(!ips.contains(remoteIp)){
                      throw new DisabledException("無(wú)權(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ā)生錯(cuò)誤 : " + ex.getMessage());
        }
    }
    @Override
    public boolean supports(Class<?> arg0) {
        return true;
    }
}

4、主服務(wù)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 {
    /**
      刪除請(qǐng)求頭文件
     */
    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拿到剛進(jìn)來(lái)的請(qǐng)求數(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);
                        //刪除的請(qǐng)求頭
                        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、主服務(wù)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、直接訪問(wèn)主服務(wù)接口,不登錄無(wú)法訪問(wèn)

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

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

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

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

相關(guān)文章

  • 探索Java I/O 模型的演進(jìn)

    探索Java I/O 模型的演進(jìn)

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

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

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

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

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

    Java調(diào)用通義千問(wèn)API的詳細(xì)步驟

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

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

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

    SpringBoot基于配置實(shí)現(xiàn)短信服務(wù)策略的動(dòng)態(tài)切換

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

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

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

    JAVA實(shí)現(xiàn)RSA簽名、驗(yàn)簽全過(guò)程

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

    SpringAOP事務(wù)配置語(yǔ)法及實(shí)現(xiàn)過(guò)程詳解

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

    深入理解Java設(shè)計(jì)模式之原型模式

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

最新評(píng)論

河西区| 德庆县| 久治县| 夏津县| 农安县| 长顺县| 松阳县| 东山县| 博乐市| 屯昌县| 新营市| 寿阳县| 蛟河市| 襄汾县| 阜南县| 诸暨市| 信丰县| 额济纳旗| 高清| 寻甸| 腾冲县| 开原市| 上杭县| 安吉县| 泰州市| 泸水县| 绥江县| 兴城市| 泽库县| 孟州市| 大埔县| 大宁县| 中山市| 海原县| 榆林市| 萍乡市| 永胜县| 无极县| 滁州市| 富平县| 井冈山市|