实现登录验证

article/2025/10/10 3:24:09

    最近练习搭建了一个后台管理系统,首先第一步做了关于验证登录的功能.以下项目使用了Nacos作为服务发现和注册中心,将Auth和gateway,system等相关多个微服务注册进Nacos.每次刷新登录页面,就会获取新的验证码(,输入正确的验证码即可成功跳转至首页.

    

获取验证码url:http://localhost/dev-api/code - dev-api是前端设置的反向代理,实际访问的是网关路径和端口.即在网关gateway模块做了路由转发.返回给前端

/*** 路由转发*/
@Configuration
public class RouterFunctionConfiguration {@Autowiredprivate ValidateCodeHandler validateCodeHandler;@Beanpublic RouterFunction routerFunction() {return RouterFunctions.route(RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),validateCodeHandler);}
}/**
*验证码Handler
*/
@Component
public class ValidateCodeHandler implements HandlerFunction<ServerResponse> {@Autowiredprivate ValidateCodeService validateCodeService;@SneakyThrows@Overridepublic Mono<ServerResponse> handle(ServerRequest serverRequest) {AjaxResult result =  validateCodeService.createCapcha();//TODO catch returnreturn    ServerResponse.status(HttpStatus.OK).body(BodyInserters.fromValue(result));}
}
public interface ValidateCodeService {/*** 生成验证码*/AjaxResult createCapcha() throws IOException;//, CaptchaException/*** 校验验证码*/void checkCapcha(String key, String value) ;//throws CaptchaException
}/*** 验证码服务*/
@Service
@Slf4j
public class ValidateCodeServiceImpl implements ValidateCodeService {@Autowiredprivate RedisUtil redisUtil;//    @Autowired
//    Producer defaultKaptcha;@Resource(name = "captchaProducerMath")private Producer defaultKaptcha;@Overridepublic AjaxResult createCapcha() {AjaxResult ajax = AjaxResult.success();// 生成验证码String capText = defaultKaptcha.createText();System.out.println("capText....."+ capText);BufferedImage image = defaultKaptcha.createImage(capText);String uuid = IdUtils.simpleUUID();String redis_key = Constants.CAPTCHA_CODE_KEY + uuid;System.out.println("createCapcha redis_key capText"+ redis_key +"-"+ capText);redisUtil.setCacheObject(redis_key, capText, 3, TimeUnit.MINUTES);FastByteArrayOutputStream os = new FastByteArrayOutputStream();try {ImageIO.write(image, "jpg", os);} catch (IOException e) {log.error("ImageIO write error", e);return AjaxResult.error(e.getMessage());}ajax.put("uuid", uuid);ajax.put("img", Base64.encode(os.toByteArray()));return ajax;}@Overridepublic void checkCapcha(String key, String code) {if(StringUtils.isEmpty(code)){//验证码不能为空throw new ObjectNotNullException("验证码不能为空");}//从redis获取 redis_keyString redis_key = Constants.CAPTCHA_CODE_KEY + key;//获取redis_key 对应的 redis_valueString redis_value = redisUtil.getCacheObject(redis_key);if(StringUtils.isEmpty(redis_value)){//验证码失效throw new RuntimeException("验证码失效");}//用了验证码之后从redis删除redisUtil.deleteCacheObject(redis_key);if(!redis_value.equals(code)){//可以修改为忽略大小写//验证码错误throw new RuntimeException("验证码错误");}}
}/**
*验证码样式配置
*/
@Configuration
public class KaptchaConfig {//验证码样式@Bean(name = "captchaProducerMath")public DefaultKaptcha getKaptchaBeanMath(){DefaultKaptcha defaultKaptcha = new DefaultKaptcha();Properties properties = new Properties();// 是否有边框 默认为true 我们可以自己设置yes,noproperties.setProperty(KAPTCHA_BORDER, "yes");// 边框颜色 默认为Color.BLACKproperties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");// 验证码文本字符颜色 默认为Color.BLACKproperties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");// 验证码图片宽度 默认为200properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");// 验证码图片高度 默认为50properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");// 验证码文本字符大小 默认为40properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");// KAPTCHA_SESSION_KEYproperties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");// 验证码文本生成器
//        properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.gateway.config.KaptchaTextCreator");// 验证码文本字符间距 默认为2properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");// 验证码文本字符长度 默认为5properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");// 验证码噪点颜色 默认为Color.BLACKproperties.setProperty(KAPTCHA_NOISE_COLOR, "white");// 干扰实现类properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpyproperties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");Config config = new Config(properties);defaultKaptcha.setConfig(config);return defaultKaptcha;}
}

 登录验证用户名密码,验证码是否正确

auth模块提供对外验证的接口负责调用system模块验证成功生成并设置token等信息,system模块提供用户信息查询,登录之前会经gateway转发到后台微服务,将验证码校验的功能放到了网关处.

在gateway模块中加入了自定义的验证码过滤器,特定的访问路径,会先执行验证码filter.例如:login

/*** 验证码过滤器*/
public class ValidateFilter extends AbstractGatewayFilterFactory {@Autowiredprivate ValidateCodeService validateCodeService;private static final String CODE = "code";private static final String UUID = "uuid";@Overridepublic GatewayFilter apply(Object config) {return (exchange, chain)->{System.out.println("打印线程id........"+Thread.currentThread());//2System.out.println("ValidateFilter apply ...");//3ServerHttpRequest request = exchange.getRequest();String path = request.getURI().getPath();System.out.println("path..." + path);//4//1.路径不是login和register,不检验验证码,直接放行if(!path.equals("/auth/login")){return chain.filter(exchange);}//2.校验验证码try {Flux<DataBuffer> body = request.getBody();AtomicReference<String> bodyRef = new AtomicReference<>();Consumer<? super DataBuffer> c = (b ->{System.out.println(b.toString()+"lll...");//c...c 之间执行CharBuffer charBuffer = StandardCharsets.UTF_8.decode(b.asByteBuffer());DataBufferUtils.release(b);bodyRef.set(charBuffer.toString());});System.out.println("c..........."+c.toString());//5body.subscribe(c);System.out.println("c..........."+c.toString()+"end");//6String rspStr = bodyRef.get();System.out.println("rspStr");//7JSONObject obj = JSONObject.parseObject(rspStr);System.out.println("obj");//8
//                if(obj != null){System.out.println("checkCapcha...");//9String code = obj.getString(CODE);String uuid = obj.getString(UUID);validateCodeService.checkCapcha(uuid, code);
//                }System.out.println("ooooooooooooo");//10}catch (Exception e){
//                   throw new RuntimeException("验证码校验失败!");System.out.println("e.getMessage()"+e.getMessage());//9return ServletUtils.webFluxResponseWriter(exchange.getResponse(), e.getMessage());}System.out.println("apply end........");return chain.filter(exchange);};}
}

如果验证码校验成功,则会转发到后台真正执行登录的接口,完成登录验证,即调用auth微服务

在auth服务中,提供了login接口:
 


@RestController
public class TokenController {@Autowiredprivate ITokenService tokenService;@Autowiredprivate ILoginService loginService;@PostMapping("/login")public Result<?> login(@RequestBody LoginDTO loginDTO) {System.out.println("查询登录信息开始...");//查询当前用户信息查询接口SysUser sysUser = loginService.login(loginDTO.getUsername(), loginDTO.getPassword());if(sysUser == null){throw new ObjectNotExistException("用户信息不存在");}//创建令牌信息Map<String,Object> tokenInfo = tokenService.createToken(new LoginUser(sysUser.getUserId(), sysUser.getUserName()));System.out.println("查询登录信息结束...");return Result.ok(tokenInfo);}
}@Service("tokenService")
public class TokenService implements ITokenService {/*** 创建令牌*/public Map<String, Object> createToken(LoginUser loginUser) {String token = IdUtils.fastUUID();String userName = loginUser.getUsername();Long userId = loginUser.getUserId();loginUser.setToken(token);//TODO 刷新token生效时间
//        refreshToken(loginUser);// Jwt存储信息Map<String, Object> claimsMap = new HashMap<>();claimsMap.put(SecurityConstants.USER_KEY, token);claimsMap.put(SecurityConstants.DETAILS_USERNAME, userName);claimsMap.put(SecurityConstants.DETAILS_USER_ID, userId);//TODO userId deptId等额外信息存储// 接口返回信息Map<String, Object> rspMap = new HashMap<>();rspMap.put("access_token", JwtUtils.createToken(claimsMap));
//        rspMap.put("expires_in", expireTime);return rspMap;}
//    /**
//     * 刷新令牌有效期
//     *
//     * @param loginUser 登录信息
//     */
//    public void refreshToken(LoginUser loginUser)
//    {
//        loginUser.setLoginTime(System.currentTimeMillis());
//        loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
//        // 根据uuid将loginUser缓存
//        String userKey = getTokenKey(loginUser.getToken());
//        redisService.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
//    }}

登陆成功,会创建token信息返回前端,前端会拿着token访问其他业务接口,会通过网关的校验,验证token信息是否有效.


/*** 网关鉴权  验证token* 1. 用户进入网关开始登陆,网关过滤器进行判断,如果是登录,则路由到后台管理微服务进行登录* 2. 用户登录成功,后台管理微服务签发JWT TOKEN信息返回给用户* 3. 用户再次进入网关开始访问,网关过滤器接收用户携带的TOKEN* 4. 网关过滤器解析TOKEN ,判断是否有权限,如果有,则放行,如果没有则返回未认证错误*/
public class AuthFilter implements GlobalFilter, Ordered {@Autowiredprivate IgnoreWhiteProperties ignoreWhiteProperties;@SneakyThrows@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String url = exchange.getRequest().getURI().getPath();//url验证 TODO 放行 loginif(matchUrls(url)){//匹配return chain.filter(exchange);}else{String token =  exchange.getRequest().getHeaders().getFirst("Authorization");if(StringUtils.isEmpty(token)){exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);System.out.println("token缺失!");return unauthorizedResponse(exchange, "token缺失!");}else{//验证tokenClaims claims = JwtUtils.parseToken(token);if(ObjectUtils.isEmpty(claims)){System.out.println("验证信息无效!");return unauthorizedResponse(exchange, "验证信息无效!");}//TODO 从redis取值,如果不存在则token验证过期 (d)
//TODO                boolean login = true;
//TODO                if(!login){
//TODO                    throw new Exception("token过期!");//TODO TokenException
//TODO                }String userName = JwtUtils.getUserName(claims);String userId = JwtUtils.getUserId(claims);if(!StringUtils.isEmpty(userName) && !StringUtils.isEmpty(userId)){//身份认证成功,设置请求值Consumer<HttpHeaders> httpHeaders = httpHeader -> {httpHeader.add(SecurityConstants.USER_KEY, token);httpHeader.add(SecurityConstants.DETAILS_USERNAME, userName);httpHeader.add(SecurityConstants.DETAILS_USER_ID, userId);};exchange.getRequest().mutate().headers(httpHeaders);//TODO 内部請求來源參數清除}else{//身份认证失败return unauthorizedResponse(exchange, "验证信息无效!");}}}return chain.filter(exchange);}private boolean matchUrls(String url){System.out.println("url :" +url);List<String> whites = ignoreWhiteProperties.getWhites();if(CollectionUtils.isEmpty(whites)){return false;}for(String u : whites){System.out.println("u : " + u);if(isMatch(url, u)){return true;}}return false;}//比较private boolean isMatch(String url, String match) {
//        AntPathMatcher matcher = new AntPathMatcher();
//        matcher.match(url, match);return url.contains(match);}@Overridepublic int getOrder() {return Ordered.HIGHEST_PRECEDENCE;}private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg){System.out.println("[鉴权异常处理]请求路径:"+exchange.getRequest().getPath());return ServletUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.UNAUTHORIZED.value());}
}

可以再白名单中添加不需要校验token的url

在验证码过滤器中Flux<DataBuffer> body = request.getBody();可能取值为null,原因百度了说是流不能重复读取的问题,添加如下配置即可解决

@Component
public class CacheRequestFilter extends AbstractGatewayFilterFactory<CacheRequestFilter.Config>
{public CacheRequestFilter(){super(Config.class);}@Overridepublic String name(){return "CacheRequestFilter";}@Overridepublic GatewayFilter apply(Config config){System.out.println("CacheRequestFilter apply...");CacheRequestGatewayFilter cacheRequestGatewayFilter = new CacheRequestGatewayFilter();Integer order = config.getOrder();if (order == null){return cacheRequestGatewayFilter;}return new OrderedGatewayFilter(cacheRequestGatewayFilter, order);}public static class CacheRequestGatewayFilter implements GatewayFilter{@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain){System.out.println("CacheRequestFilter filter...");//1// GET DELETE 不过滤HttpMethod method = exchange.getRequest().getMethod();if (method == null || method.matches("GET") || method.matches("DELETE")){return chain.filter(exchange);}return DataBufferUtils.join(exchange.getRequest().getBody()).map(dataBuffer -> {byte[] bytes = new byte[dataBuffer.readableByteCount()];dataBuffer.read(bytes);DataBufferUtils.release(dataBuffer);return bytes;}).defaultIfEmpty(new byte[0]).flatMap(bytes -> {DataBufferFactory dataBufferFactory = exchange.getResponse().bufferFactory();ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(exchange.getRequest()){@Overridepublic Flux<DataBuffer> getBody(){if (bytes.length > 0){return Flux.just(dataBufferFactory.wrap(bytes));}return Flux.empty();}};return chain.filter(exchange.mutate().request(decorator).build());});}}@Overridepublic List<String> shortcutFieldOrder(){return Collections.singletonList("order");}static class Config{private Integer order;public Integer getOrder(){return order;}public void setOrder(Integer order){this.order = order;}}
}

为了获取当前用户的信息,可以通过session获取,我通过吧用户的token解析放到了private static final TransmittableThreadLocal<Map<String, Object>> THREAD_LOCAL中,添加了一个头信息拦截器

/*** 请求头拦截器 : 内部请求身份验证拦截器* AsyncHandlerInterceptor : https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/AsyncHandlerInterceptor.html*/
public class HeaderInterceptor implements AsyncHandlerInterceptor {//1.Thread_local验证//2.session验证@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("HeaderInterceptor preHandle ....开始执行");//↓↓↓↓↓↓↓↓//1.Thread_local验证方式// 如果不是映射到方法直接通过if(!(handler instanceof HandlerMethod)){return true;}//从网关中获取的String userId = request.getHeader(SecurityConstants.DETAILS_USER_ID);String userName = request.getHeader(SecurityConstants.DETAILS_USERNAME);String userkey = request.getHeader(SecurityConstants.USER_KEY);SecurityContextHolder.setThreadLocal(SecurityConstants.DETAILS_USER_ID, userId == null ? "": userId);SecurityContextHolder.setThreadLocal(SecurityConstants.DETAILS_USERNAME, userName == null ? "" : userName);SecurityContextHolder.setThreadLocal(SecurityConstants.USER_KEY, userkey == null ? "" : userkey);//TODO 获取token,获取userid,username,userkeyString token = SecurityUtils.getToken();if (StringUtils.isNotEmpty(token)){TODO LoginUser详情 获取当前登录信息LoginUser loginUser = AuthUtil.getLoginUser(token);if (StringUtils.isNotNull(loginUser)) {//TODO 验证有效期AuthUtil.verifyLoginUserExpire(loginUser);SecurityContextHolder.setThreadLocal(SecurityConstants.LOGIN_USER, loginUser);
//                return true;}//TODO 为什么不校验该token解析出来的user是否合法
//            else{
//                //TODO login无效报错
//                System.out.println("login信息,不存在");
//                throw new RuntimeException("用户未登录,请登录后操作!");
//            }}//TODO 为什么不校验token,直接返回true???
//        else{
//            //
//            //TODO  token不能为空
//            System.out.println("token为空!");
//            throw new RuntimeException("用户未登录,请登录后操作!");
//        }//↑↑↑↑↑↑System.out.println("HeaderInterceptor preHandle ....结束执行");return true;}@Overridepublic void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//        AsyncHandlerInterceptor.super.afterConcurrentHandlingStarted(request, response, handler);System.out.println("afterConcurrentHandlingStarted");}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion");//TODO 放开注释SecurityContextHolder.remove();}
}

就可以通过SecurityContextHolder工具类获取当前登录用户的信息.还可以刷新token的有效期(代码暂无).


http://chatgpt.dhexx.cn/article/VxyEtMEb.shtml

相关文章

【图解】用户登录验证流程,这下彻底搞懂了!

开发者&#xff08;KaiFaX&#xff09; 面向全栈工程师的开发者 专注于前端、Java/Python/Go/PHP的技术社区 本文通过图示及代码的方式介绍用户登录流程及技术实现&#xff0c;内容包括用户登录&#xff0c;用户验证&#xff0c;如何获取操作用户的信息以及一些黑名单及匿名接口…

前端应该掌握的登录认证知识

1 背景 前一段时间&#xff0c;参与了老项目的迁移工作&#xff0c;配合后端接口迁移时&#xff0c;由于两个项目采取了不一样的登陆方案&#xff0c;所以遇到了跨域登录态无法共享的问题。经过各方协调&#xff0c;最终老项目将迁移页面部署在新项目的指定网关下&#xff0c;…

中间件登录验证(白名单,黑名单)

中间件版的登录验证需要依靠session&#xff0c;所以数据库中要有django_session表。 urls.py from django.conf.urls import url from app01 import viewsurlpatterns [url(r^index/$, views.index),url(r^login/$, views.login, namelogin), ]urls.py View Code views.py fr…

登录验证的那些事儿

前言 在以前的项目我们一般使用session或者cookie来存储已登录的用户信息&#xff0c;这样到达一个免除重复登录的问题&#xff0c;那么如何登录&#xff0c;又如何验证&#xff0c;就是一直在讨论的问题。今天我们对这些技术点进行一个梳理。 字 多 你 就 挑 有 颜 色 的 看…

计算机网络-(自顶向下方法)

计算机网络基础知识概述 计算机网络学习的核心内容就是网络协议的学习。网络协议是为计算机网络中进行数据交换而建立的规则、标准或者说是约定的集合。因为不同用户的数据终端可能采取的字符集是不同的&#xff0c;两者需要进行通信&#xff0c;必须要在一定的标准上进行。 …

计算机网络:自顶向下方法 笔记

计算机网络&#xff1a;自顶向下方法 笔记 综述因特网部件图例交换方式分组交换电路交换频分复用时分复用 对比 五层/七协议一个传输实例攻击DOS攻击 应用层应用程序结构客户-服务器结构P2P point2point结构 应用层协议总览http报文格式http状态码cookiesessionhttps FTPSMTPDN…

计算机网络 自顶向下 笔记

目录 第一章 计算机网络和因特网 全书答案评论留言即可 我私发&#xff0c;这里上传不了文本 第一章 计算机网络和因特网 什么是因特网&#xff1f; 因特网的具体构成&#xff1a;构成因特网的基本硬件和软件组件 分布式应用的互联网基础设施来描述 ---------------------…

《计算机网络-自顶向下》04. 网络层-数据平面

文章目录 网络层数据平面和控制平面两者的概述数据平面控制平面 控制平面&#xff1a;传统方法控制平面&#xff1a;SDN 方法网络服务模型 路由器工作原理通用路由器体系结构输入端口的功能基于目标的转发 交换结构内存交换方式总线交换方式纵横式交换方式 输出端口的功能何时何…

计算机网络自顶向下方法 习题参考答案 第一章

复习题&#xff1a; R1. 没有什么不同。PC、服务器、手机等。Web服务器是端系统。 R2. Protocol is commonly described as a set of international courtesy rules. These well-established and time-honored rules have made it easier for nations and people to live a…

计算机网络自顶向下方法(第六版) 课后题答案 | 第三章

复习题 R1. a. 将此协议称为简单传输协议(STP)。在发送方端&#xff0c;STP 从发送过程中接收不超过 1196 字节的数据块、目标主机地址和目标端口号。STP 向每个块添加一个 4 字节的报头&#xff0c;并将目标进程的端口号放在这个报头中。然后 STP 将目标主机地址和报文段提供…

计算机网络—自顶向下 计算机网络和因特网

目录 1. 什么是计算机网络 1.1 概念 1.2 因特网的具体构成 2. 计算机网络的结构 2.1 网络边缘(The Network Edge) 2.1.1 接入网 2.1.2 物理媒体 2. 2 网络核心(The network core) 2.2.1 电路交换 2.2.2 多路复用 2.2.3 报文交换 2.2.4 分组交换 2.2.5 网络之…

计算机网络自顶向下方法(一)——计算机网络和因特网

不要成为理想的巨人&#xff0c;行动的矮子 文章目录 写在前面什么是Internet?具体构成及描述什么是Internet: 从服务角度 网络边缘网络边缘&#xff1a;采用网络设施的面向连接服务网络边缘&#xff1a;采用基础设施的无连接服务 网络核心网络核心&#xff1a;电路交换电路交…

【计算机网络:自顶向下方法】(二)应用层

tm 【计算机网络&#xff1a;自顶向下方法】(二)应用层 文章目录 应用层如何创建一个新的网络应用? 2.1 应用层原理网络应用的体系结构对等模式(P2P:Peer To Peer)混合体&#xff1a;客户-服务器和对等体系结构 进程通信分布式进程通信需要解决的问题问题1&#xff1a;…

计算机网络自顶向下-第 8 版

Computer Networking A Top Down Approach 8th Edition Computer Networking A Top Down Approach 8th Edition 概述本书资源计算机网络自顶向下方法第八版英文pdf图片预览 更新特点精彩试读作者介绍 概述 概述 Computer Networking A Top Down Approach第8版也就是计算机网…

自顶向下计算机网络 传输层

自顶向下计算机网络学习 传输层 一、概述和传输层服务1.1 传输层提供的服务1.2传输层和网络层的关系1.3 传输层协议可靠的、保序的传输&#xff1a;TCP不可靠、不保序的传输&#xff1a;UDP 二、多路复用与解复用2.1 什么是复用与解复用2.2 面向连接(TCP)的多路复用与分解2.3 无…

自顶向下计算机网络学习 应用层

自顶向下计算机网络学习 应用层 一、应用层协议原理1. 网络应用的体系结构1.1 客户-服务器&#xff08;C/S&#xff09;体系结构1.2 对等体(P2P)体系结构1.3 混合体&#xff1a;客户 - 服务器和对等体系结构 2.应用进程间的通信2.1 分布式进程需要解决的问题2.1.1 进程标识和寻…

计算机网络自顶向下方法 【第一章 计算机网络及因特网】

目录 1.1 什么是因特网1.1.1 具体构成描述1.1.2 服务描述1.1.3 网络协议 1.2 网络边缘1.2.1 接入网 1.3 网络核心1.3.1分组交换1.3.2 电路交换1.3.3 报文交换 1.4 交换网中的时延&#xff0c;丢包和吞吐量1.5 协议层次及其服务模型 1.1 什么是因特网 我们可以用两种方式描述因…

计算机网络自顶向下方法笔记01

《计算机网络自顶向下方法》学习笔记。之前学习过计算机网络微课&#xff0c;已经对计网中的很多概念都有了印象和一定的了解了&#xff0c;这时候再读自顶向下感觉比较轻松了。这本书没有涉及太多物理层的内容&#xff0c;第一章为概述。从第二章应用层开始&#xff0c;自顶向…

《计算机网络--自顶向下方法》第一章--计算机网络和英特网

1.1什么是英特网 1.1.1具体构成描述 主机&#xff08;host&#xff09;或端系统&#xff08;end system&#xff09;&#xff1a;所有与因特网相连的计算设备 路由器&#xff08;router&#xff09;&#xff1a;从一条入通信链路接收到达的分组&#xff0c;并通过一条出通信链…

计算机网络(自顶向下方法)-网络层

计算机网络&#xff08;自顶向下方法&#xff09;-网络层 4. 1 导论数据平面控制平面 4.2 路由器组成4.3 IP: Internet Protocol数据报格式分片IPv4地址子网IP 地址分类子网掩码(subnet mask)如何获得一个IP地址DHCP: Dynamic Host Configuration Protocol NAT&#xff1a;网络…