当前位置:首页 >> 摄影技巧 >> 佳能镜头三码合一都在哪里,佳能200dii鱼眼拍摄模式

佳能镜头三码合一都在哪里,佳能200dii鱼眼拍摄模式

佳能EF8-15mmf/4LUSM鱼眼镜头在不同焦距时的圆形鱼眼效果佳能EF8-15mmf/4LUSM鱼眼镜头在不同焦距时的对角线鱼眼效果佳能镜头三码是指佳能公司制造的每个镜头都有三个辨识度高且唯一的编码:

阅读数:22

佳能镜头三码合一的优点在于简化了镜头设计?就可以打开盒子,能取出机器了,首先要做的就是核对三码:机身编码、保修卡编码、包装盒编码。只有在“三码合一”时,才能证明这是佳能正品行货产品,差一个数字都不行。如果购买的是套机产品,包装盒上会有两组序列号,上面一组是机身的,下面一组是镜头的,镜头也需要三码合一。

佳能镜头三码合一

作为摄影师,我们对于相机镜头的选择非常重视。而在众多品牌中,佳能的镜头往往备受摄影师们的青睐。佳能镜头三码合一是佳能公司推出的一种全新镜头分类标准,那么这种三码合一镜头到底能说明什么呢?

除此之外,佳能镜头三码合一还能说明佳能公司在摄影行业中不断创新和引领的精神。通过三码合一的形式,佳能为广大摄影师提供了一种更直观、更便捷的信息传递方式。这种创新能力使得佳能得以在激烈的市场竞争中不断发展壮大。

关于“佳能镜头三码合一就一定是真的吗?”的问题,需要从以下几个方面进行分析:

佳能镜头三码合一的优点在于简化了镜头设计,避免了用户在使用过程中需要频繁切换环的繁琐操作。然而,三码合一也有一些缺点。三码合一的印刷会占用相当一部分镜头表面,降低了外观美感;一些用户可能需要更为详尽的参数信息,在使用时可能需要查看不同的环上的标识。

“佳能相机的三码合一”其实是指相机的“曝光参数信息”,也就是ISO、快门和光圈三种参数。在佳能相机中,这三种曝光参数信息可以在一张照片的Exif信息中合并为一种信息,“三码合一”,方便我们查看照片拍摄时的曝光参数。如何检查三码合一呢?方法如下:

1.拍摄照片:我们需要使用佳能相机进行拍摄,这样才能在相片的Exif信息中查到三码合一的信息。

2.查看相片属性:在拍摄完毕后,我们可以将相片导入电脑,右键选择“属性”打开“详细信息”界面,在界面下方找到“文件信息”一栏,便可看到这张照片的Exif信息,其中包括曝光参数的具体数值。

3.检查曝光参数:在Exif信息中查看曝光参数,在佳能相机中,三码合一通常显示为一个数字,例如“200”,代表ISO200,快门速度1/200s,光圈f/2.8。我们可以查看这个数字,根据ISO的范围,例如佳能相机一般的ISO范围为100-6400,如果这个数字超出这个范围,就说明相片的Exif信息中不是三码合一。

4.检查软件:如果你是用其他软件查看照片,有时候可能无法显示三码合一的信息,这是因为这些软件不支持查看Exif信息,或者显示方式不同。可尝试用其他软件查看,例如Lightroom,Photoshop等专业的图片处理软件。

佳能三码合一镜头码在哪儿

在摄影领域,我们经常会听到“佳能镜头三码合一就一定是真的吗?”这样的说法。实际上,这种说法不完全正确。下面我将从以下三个方面详细探讨这个话题。

应该是机身、包装盒、保修卡上面的序列号一致,才是所谓的“三码合一”。镜头是另外的,也应该三码合一。

回答这个问题需要先了解到,这个“99新佳能拆箱需要三码合一吗?”的说法,是指在某些电商平台上,需要消费者在购买佳能相机时提供“序列号+验证代码+MAC地址”的合一信息来核实产品的合法性。从某种程度上来说,是为了防止假冒产品的出现。

你可以打佳能的官方电话。或者上佳能官网上查询。电话和官网你可以百度。貌似机身上的防伪码不是贴上去的。机身上的防伪码你一查就知道是行货还是水货了。

三码合

一:

1、手机串号(键盘上输入*#06#)。

2、手机机身标签上印出的串号,也就是电池仓的标签。

3、手机包装盒上的盒标串号,所谓的三码合一就是这三码的串号是一致的就叫三码合一。水货手机是三码合一吗?水货手机不可能做到三码合一的?以为水货的手机大多都是从国外私自运到国内销售的,一般情况下,水货是二码合一,也就是手机串码=手机机身标签上印的串码是一致的。因为渠道的原因,是将手机和包装是分开的,走私过来的时候是手机+电池,这样过来的!配件和包装都是另外途径过来的!一般情况是不会三码合一的!都打乱了,怎么还能三码合一的!但是,二码是一定的!要注意查看。水货手机原封有作用吗?还是上面的问题,水货手机都是商家或者个人走私过来的,当然不可能存在原封性,就算是原封!你敢要么?商家采购手机,不可能不检测里面手机是否完好的!

佳能镜头验证码在哪里

一.前言

SpringSecurityOAuth2手机短信验证码模式

SpringSecurityOAuth2密码模式

SpringSecurityOAuth2验证码模式

SpringSecurityOAuth2默认实现的四种授权模式在实际的应用场景中往往满足不了预期,如以下需求:

授权对象分多个用户体系,例如系统用户和会员用户;在密码授权模式的基础上加个验证码校验;基于SpringSecurityOAuth2实现手机和短信验证码登录;

相信你会遇到但不仅限上面的场景,但多少有不全面和实现复杂的通病,一度会让你觉得SpringSecurityOAuth2很难,Spring在实现核心功能基础上同时还提供了很多的扩展点,

本篇将以实战为主,原理为辅的方式,本着全面、最少改动的原则去对SpringSecurityOAuth2授权模式的扩展,本篇涉及内容如下:

SpringCloudGateway微服务网关WebFlux整合谷歌验证码Kaptcha;SpringBoot整合阿里云SMS短信服务;SpringSecurityOAuth2认证授权模式底层源码分析;SpringSecurityOAuth2扩展验证码授权模式;SpringSecurityOAuth2扩展手机短信验证码授权模式;SpringSecurityOAuth2多用户体系刷新模式;vue-element-admin后台管理前端登录接入验证码授权模式;uni-appH5、移动端手机验证码登录接入手机短信验证码授权模式。

本篇文章涉及所有的代码地址:

项目名称

码云

GitHub

微服务后台

youlai-mall

youlai-mall

管理前端

mall-admin-web

mall-admin-web

mall-app

mall-app

因为涉及的内容很多,文章中做不到把所有的代码完全贴出来,但是放心源码全部在线的,同样文档也是

二.验证码授权模式

1.原理

验证码授权模式是在密码模式基础添加个验证码校验,如果你有不管功夫怎样,能打赢你的就是好功夫这样的心态完全可以使用过滤器实现,但如果想不开的话那就试下扩展吧。

因为是基于密码授权模式的扩展,就先了解密码授权模式的流程吧。因为其他几种授权模式和密码模式实现原理都是一样,弄明白密码授权模式之后其他授权模式包括如何去扩展都是轻车熟路。

密码模式流程:根据请求参数grant_type的值password匹配到授权者ResourceOwnerPasswordTokenGraner,授权者委托给认证提供者管理器ProviderManager,根据token类型匹配到提供者DaoAuthenticationProvider,Provider从数据库获取用户认证信息和客户端请求传值的用户信息进行认证密码判读,验证通过之后返回token给客户端。

下面密码授权模式时序图贴出关键类和方法,断点走几遍流程就应该知道流程。

验证码授权模式时序图如下,仔细比对下和密码授权模式的区别。

比较可知两者的区别基本就是授权者Granter的区别,后续的Provider获取用户认证信息和密码判断完全一致,具体新增的验证码模式授权者CaptchaTokenGranter和密码模式的授权者ResourceOwnerPasswordTokenGraner区别在于前者的getOAuth2Authentication()方法获取认证信息添加了校验验证码的逻辑,具体的代码实现在实战里交待。

2.实战

验证码授权模式涉及SpringSecurityOAuth2扩展验证码授权模式、后台生成验证码和前端登录加入验证码三部分,涉及到前后端的东西,针对自己需要选择关注点即可。

2.1验证码授权模式扩展

从原理得知只需重写Granter为其添加校验验证码的能力,所以复制密码模式的授权者ResourceOwnerPasswordTokenGranter然后重名为CaptchaTokenGranter,稍加改动成为验证码模式的授权者。

CaptchaTokenGranter

复制代码1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677JAVA/***验证码授权模式授权者**@author<ahref="mailto:TokenRequest)*@seeorg.springframework.security.oauth2.provider.token.AbstractTokenGranter#grant(String,TokenRequest)*/privatestaticfinalStringGRANT_TYPE="captcha";privatefinalAuthenticationManagerauthenticationManager;privateStringRedisTemplateredisTemplate;publicCaptchaTokenGranter(AuthorizationServerTokenServicestokenServices,ClientDetailsServiceclientDetailsService,OAuth2RequestFactoryrequestFactory,AuthenticationManagerauthenticationManager,StringRedisTemplateredisTemplate){super(tokenServices,clientDetailsService,requestFactory,GRANT_TYPE);this.authenticationManager=authenticationManager;this.redisTemplate=redisTemplate;}@OverrideprotectedOAuth2AuthenticationgetOAuth2Authentication(ClientDetailsclient,TokenRequesttokenRequest){Map<String,String>parameters=newLinkedHashMap(tokenRequest.getRequestParameters());//验证码校验逻辑StringvalidateCode=parameters.get("validateCode");Stringuuid=parameters.get("uuid");Assert.isTrue(StrUtil.isNotBlank(validateCode),"验证码不能为空");StringvalidateCodeKey=AuthConstants.VALIDATE_CODE_PREFIX+uuid;//从缓存取出正确的验证码和用户输入的验证码比对StringcorrectValidateCode=redisTemplate.opsForValue().get(validateCodeKey);if(!validateCode.equals(correctValidateCode)){thrownewBizException("验证码不正确");}else{redisTemplate.delete(validateCodeKey);}Stringusername=parameters.get("username");Stringpassword=parameters.get("password");//移除后续无用参数parameters.remove("password");parameters.remove("validateCode");parameters.remove("uuid");//和密码模式一样的逻辑AuthenticationuserAuth=newUsernamePasswordAuthenticationToken(username,password);((AbstractAuthenticationToken)userAuth).setDetails(parameters);try{userAuth=this.authenticationManager.authenticate(userAuth);}catch(AccountStatusExceptionvar8){thrownewInvalidGrantException(var8.getMessage());}catch(BadCredentialsExceptionvar9){thrownewInvalidGrantException(var9.getMessage());}if(userAuth!=null&&userAuth.isAuthenticated()){OAuth2RequeststoredOAuth2Request=this.getRequestFactory().createOAuth2Request(client,tokenRequest);returnnewOAuth2Authentication(storedOAuth2Request,userAuth);}else{thrownewInvalidGrantException("Couldnotauthenticateuser:"+username);}}}

上面相对密码模式的授权者做了两处改动,总结如下:

修改GRANT_TYPE的值password为captcha;getOAuth2Authentication()方法添加验证码校验逻辑。

AuthorizationServerConfig

在AuthorizationServerConfig配置类重写TokenGranter让其支持新增的验证码模式授权者CaptchaTokenGranter

到此,SpringSecurityOAuth2扩展验证码授权大功告成!!!

怎么样,简不简单?相信你有可能心存怀疑,那先做个测试吧。

管理前端的客户端ID是mall-admin-web,在测试之前,先赋予客户端支持验证码模式。

在登录界面输入错误的验证码和正确的验证码各一次看下效果,是不是能达到预期的效果,还有验证码如何生成和前端如何传值放在后文说。

2.2SpringWebFlux整合验证码Kaptcha

验证码生成的功能主要是生成一个随机码将其缓存redis,返回redis的key标识和随机码的图片给前端。因为没有任何业务逻辑,故这里直接放在网关,除了利用WebFlux性能优势之外还能减少一次转发。youlai-gateway验证码相关代码结构图如下:

CaptchaHandler

复制代码1234567891011121314151617181920212223242526272829303132JAVA@Component@RequiredArgsConstructorpublicclassCaptchaHandlerimplementsHandlerFunction<ServerResponse>{privatefinalProducerproducer;privatefinalStringRedisTemplateredisTemplate;@OverridepublicMono<ServerResponse>handle(ServerRequestserverRequest){//生成验证码StringcapText=producer.createText();StringcapStr=capText.substring(0,capText.lastIndexOf("@"));Stringcode=capText.substring(capText.lastIndexOf("@")+1);BufferedImageimage=producer.createImage(capStr);//缓存验证码至RedisStringuuid=IdUtil.simpleUUID();redisTemplate.opsForValue().set(AuthConstants.VALIDATE_CODE_PREFIX+uuid,code,60,TimeUnit.SECONDS);//转换流信息写出FastByteArrayOutputStreamos=newFastByteArrayOutputStream();try{ImageIO.write(image,"jpg",os);}catch(IOExceptione){returnMono.error(e);}java.util.MapresultMap=newHashMap<String,String>();resultMap.put("uuid",uuid);resultMap.put("img",Base64.encode(os.toByteArray()));returnServerResponse.status(HttpStatus.OK).body(BodyInserters.fromValue(Result.success(resultMap)));}}

CaptchaConfig

属性kaptcha.textproducer.impl需要指定你自己项目文本生成器KaptchaTextCreator的类路径

复制代码12JAVA//验证码文本生成器properties.setProperty("kaptcha.textproducer.impl","com.youlai.gateway.kaptcha.KaptchaTextCreator");

CaptchaRouter

复制代码12345678910JAVA@ConfigurationpublicclassCaptchaRouter{@BeanpublicRouterFunction<ServerResponse>routeFunction(CaptchaHandlercaptchaHandler){returnRouterFunctions.route(RequestPredicates.GET("/captcha").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),captchaHandler::handle);}}

验证码测试

修改Nacos网关配置文件youlai-gateway.yaml白名单添加请求路径/captcha

访问:9999/captcha如下:

2.3前端登录接入验证码模式

登录页面

登录表单添加验证码,完整代码地址:mall-admin-web

src/views/login/index.vue

复制代码123456789101112131415HTML<el-form-itemprop="validateCode"><span><svg-iconicon-class="validCode"/></span><el-inputv-model="loginForm.validateCode"auto-complete="off"placeholder="请输入验证码"@keyup.enter.native="handleLogin"/><div><img:src="captchaUrl"@click="getValidateCode"height="38px"/></div></el-form-item>

返回的图片是base64加密后的字符串,所以添加前缀data:image/gif;base64,

复制代码12345678JAVASCRIPT//获取验证码getValidateCode(){getCaptcha().then(response=>{const{img,uuid}=response.datathis.captchaUrl="data:image/gif;base64,"+imgthis.loginForm.uuid=uuid;})}

接口请求

src/store/modules/user.js设置请求参数

复制代码1234567891011121314151617181920JAVASCRIPTlogin({commit},userInfo){const{username,password,validateCode,uuid}=userInforeturnnewPromise((resolve,reject)=>{login({username:username,password:password,grant_type:'captcha',//授权模式指定为captcha验证码模式,原先为password密码模式uuid:uuid,//从Redis获取正确验证码的标识validateCode:validateCode//验证码}).then(response=>{const{access_token,refresh_token,token_type}=response.dataconsttoken=token_type+""+access_tokencommit('SET_TOKEN',token)setToken(token)setRefreshToken(refresh_token)resolve()}).catch(error=>{reject(error)})})

src/api/user.js请求API设置请求头部

复制代码12345678910JAVASCRIPTexportfunctionlogin(params){returnrequest({url:'/youlai-auth/oauth/token',method:'post',params:params,headers:{'Authorization':'BasicbWFsbC1hZG1pbi13ZWI6MTIzNDU2'//OAuth2客户端信息Base64加密,明文:mall-admin-web:123456}})}

三.手机短信验证码授权模式

1.原理

手机短信验证码模式时序图如下,变动的角色还是用绿色背景标识。可以看到扩展是对授权者Granter和认证提供者Provider做切入口。

手机短信验证码授权流程:流程基本上和密码模式一致,根据grant_type匹配授权者SmsCodeTokenGranter,委托给ProviderManager进行认证,根据SmsCodeAuthenticationToken的匹配认证提供者SmsCodeAuthenticationProvider进行短信验证码校验。

2.实战

2.1手机短信验证码授权模式扩展

SmsCodeTokenGranter

复制代码1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556JAVA/***手机验证码授权者**@author<ahref="mailto:TokenRequest)*@seeorg.springframework.security.oauth2.provider.token.AbstractTokenGranter#grant(String,TokenRequest)*/privatestaticfinalStringGRANT_TYPE="sms_code";privatefinalAuthenticationManagerauthenticationManager;publicSmsCodeTokenGranter(AuthorizationServerTokenServicestokenServices,ClientDetailsServiceclientDetailsService,OAuth2RequestFactoryrequestFactory,AuthenticationManagerauthenticationManager){super(tokenServices,clientDetailsService,requestFactory,GRANT_TYPE);this.authenticationManager=authenticationManager;}@OverrideprotectedOAuth2AuthenticationgetOAuth2Authentication(ClientDetailsclient,TokenRequesttokenRequest){Map<String,String>parameters=newLinkedHashMap(tokenRequest.getRequestParameters());Stringmobile=parameters.get("mobile");//手机号Stringcode=parameters.get("code");//短信验证码parameters.remove("code");AuthenticationuserAuth=newSmsCodeAuthenticationToken(mobile,code);((AbstractAuthenticationToken)userAuth).setDetails(parameters);try{userAuth=this.authenticationManager.authenticate(userAuth);}catch(AccountStatusExceptionvar8){thrownewInvalidGrantException(var8.getMessage());}catch(BadCredentialsExceptionvar9){thrownewInvalidGrantException(var9.getMessage());}if(userAuth!=null&&userAuth.isAuthenticated()){OAuth2RequeststoredOAuth2Request=this.getRequestFactory().createOAuth2Request(client,tokenRequest);returnnewOAuth2Authentication(storedOAuth2Request,userAuth);}else{thrownewInvalidGrantException("Couldnotauthenticateuser:"+mobile);}}}

SmsCodeAuthenticationProvider

复制代码123456789101112131415161718192021222324252627282930313233343536373839JAVA/***短信验证码认证授权提供者**@author<ahref="mailto:xianrui0365@163.com">xianrui</a>*@date2021/9/25*/@DatapublicclassSmsCodeAuthenticationProviderimplementsAuthenticationProvider{privateUserDetailsServiceuserDetailsService;privateMemberFeignClientmemberFeignClient;privateStringRedisTemplateredisTemplate;@OverridepublicAuthenticationauthenticate(Authenticationauthentication)throwsAuthenticationException{SmsCodeAuthenticationTokenauthenticationToken=(SmsCodeAuthenticationToken)authentication;Stringmobile=(String)authenticationToken.getPrincipal();Stringcode=(String)authenticationToken.getCredentials();StringcodeKey=AuthConstants.SMS_CODE_PREFIX+mobile;StringcorrectCode=redisTemplate.opsForValue().get(codeKey);//验证码比对if(StrUtil.isBlank(correctCode)||!code.equals(correctCode)){thrownewBizException("验证码不正确");}else{redisTemplate.delete(codeKey);}UserDetailsuserDetails=((MemberUserDetailsServiceImpl)userDetailsService).loadUserByMobile(mobile);WechatAuthenticationTokenresult=newWechatAuthenticationToken(userDetails,newHashSet<>());result.setDetails(authentication.getDetails());returnresult;}@Overridepublicbooleansupports(Class<?>authentication){returnSmsCodeAuthenticationToken.class.isAssignableFrom(authentication);}}

AuthorizationServerConfig

在认证中心配置把SmsCodeTokenGranter添加到认证器的授权类型的集合中去。

2.2阿里云免费短信申请

访问?spm=5176.10695662.1128094.7.2a6b4bee30xtJx申请阿里云免费短信试用

添加签名,等待审核通过

签名审核通过之后就可以创建AccessKey访问密钥

添加模板,国内消息→模板管理→添加模板

签名审核通过后得到AccessKey和模板审核通过得到模板CODE,

2.3SpringBoot整合阿里云SMS短信

SpringBoot整合SMS网上教程很多,这里不画蛇添足,接下来简单说下youlai-mall整合阿里云SMS短信。完整源码

按惯例把短信封装成一个公共模块以便给其他需要短信的应用模块引用。

youlai-auth引入common-sms依赖

复制代码123456XML<dependencies><dependency><groupId>com.youlai</groupId><artifactId>common-sms</artifactId></dependency></dependencies>

其中AliyunSmsProperties需要的属性需要配置在Nacos的配置中心文件youlai-auth.yaml

复制代码123456789YAML#阿里云短信配置aliyun:sms:accessKeyId:LTAI5tSxxxxxxNcD6diBJLyRaccessKeySecret:SoOWRqpjtSxxxxxxM8QZ2PZiMTJOVCdomain:dysmsapi.aliyuncs.comregionId:cn-shanghaitemplateCode:SMS_225xxx770signName:有来技术

发送短信验证码接口

复制代码12345678910111213141516JAVA@Api(tags="短信验证码")@RestController@RequestMapping("/sms-code")@RequiredArgsConstructorpublicclassSmsCodeController{privatefinalAliyunSmsServicealiyunSmsService;@ApiOperation(value="发送短信验证码")@ApiImplicitParam(name="phoneNumber",example="17621590365",value="手机号",required=true)@PostMappingpublicResultsendSmsCode(StringphoneNumber){booleanresult=aliyunSmsService.sendSmsCode(phoneNumber);returnResult.judge(result);}}

2.4移动端接入短信验证码授权模式

有来移动端mall-app使用uni-app跨平台应用的前端框架。所以uni-app的强大之处没法体现。借着这次给mall-app扩展手机短信验证码的授权模式的机会,为H5、Android和IOS添加手机短信验证码的登录界面。

H5/Android/IOS登录界面

登录页面/pages/login/login.vue在不同的平台有不同的呈现实现原理是通过#ifdefMP和#ifndefMP条件编译指令实现的,其中#ifdefMP是在小程序平台编译生效,而#ifdefMP是非小程序平台编译生效。

在开发编译时,当在HBuilderX工具栏点击运行选择不同的平台会有不同的页面呈现。

运行→运行到内置浏览器→手机短信验证码登录界面;

说到接入SpringSecurityOAuth2扩展的手机短信验证码,重要的还是看如何传参。在mall-app的/api/user.js代码:

复制代码1234567891011121314151617JAVASCRIPT//H5/Android/IOS手机短信验证码登录//#ifndefMPexportfunctionlogin(mobile,code){returnrequest({url:'/youlai-auth/oauth/token',method:'post',params:{mobile:mobile,code:code,grant_type:'sms_code'},headers:{'Authorization':'BasicbWFsbC1hcHA6MTIzNDU2'//客户端信息Base64加密,明文:mall-app:123456}})}//#endif

赋予mall-app客户端支持sms_code模式

3.测试

到此H5/Android/IOS移动端接入SpringSecurityOAuth2扩展的手机短信验证码授权模式已经完成。

1.原理

我们所扮演的角色是开发者服务器,后续小程序携带token和开发者服务器进行交互,

添加授权者WechatTokenGranter构建WechatAuthenticationToken,匹配到认证提供者WechatAuthenticationProvider,在其authenticate方法完成认证授权逻辑。

2.实战

WechatTokenGranter

encryptedData、iv构建WechatAuthenticationToken

TokenRequest)*@seeorg.springframework.security.oauth2.provider.token.AbstractTokenGranter#grant(String,TokenRequest)*/privatestaticfinalStringGRANT_TYPE="wechat";privatefinalAuthenticationManagerauthenticationManager;publicWechatTokenGranter(AuthorizationServerTokenServicestokenServices,ClientDetailsServiceclientDetailsService,OAuth2RequestFactoryrequestFactory,AuthenticationManagerauthenticationManager){super(tokenServices,clientDetailsService,requestFactory,GRANT_TYPE);this.authenticationManager=authenticationManager;}@OverrideprotectedOAuth2AuthenticationgetOAuth2Authentication(ClientDetailsclient,TokenRequesttokenRequest){Map<String,String>parameters=newLinkedHashMap(tokenRequest.getRequestParameters());Stringcode=parameters.get("code");StringencryptedData=parameters.get("encryptedData");Stringiv=parameters.get("iv");parameters.remove("code");parameters.remove("encryptedData");parameters.remove("iv");AuthenticationuserAuth=newWechatAuthenticationToken(code,encryptedData,iv);//未认证状态((AbstractAuthenticationToken)userAuth).setDetails(parameters);try{userAuth=this.authenticationManager.authenticate(userAuth);//认证中}catch(Exceptione){thrownewInvalidGrantException(e.getMessage());}if(userAuth!=null&&userAuth.isAuthenticated()){//认证成功OAuth2RequeststoredOAuth2Request=this.getRequestFactory().createOAuth2Request(client,tokenRequest);returnnewOAuth2Authentication(storedOAuth2Request,userAuth);}else{//认证失败thrownewInvalidGrantException("Couldnotauthenticatecode:"+code);}}}

WechatAuthenticationProvider

成功返回token。

=null&&ResultCode.USER_NOT_EXIST.getCode().equals(memberAuthResult.getCode())){StringsessionKey=sessionInfo.getSessionKey();StringencryptedData=authenticationToken.getEncryptedData();Stringiv=authenticationToken.getIv();//解密encryptedData获取用户信息WxMaUserInfouserInfo=wxMaService.getUserService().getUserInfo(sessionKey,encryptedData,iv);UmsMembermember=newUmsMember();BeanUtil.copyProperties(userInfo,member);member.setOpenid(openid);member.setStatus(GlobalConstants.STATUS_YES);memberFeignClient.add(member);}UserDetailsuserDetails=((MemberUserDetailsServiceImpl)userDetailsService).loadUserByOpenId(openid);WechatAuthenticationTokenresult=newWechatAuthenticationToken(userDetails,newHashSet<>());result.setDetails(authentication.getDetails());returnresult;}@Overridepublicbooleansupports(Class<?>authentication){returnWechatAuthenticationToken.class.isAssignableFrom(authentication);}}

同样是在mall-app的接口文件中/api/user.js,先让我们看下小程序端如何传值?

复制代码123456789101112131415161718JAVASCRIPT//小程序授权登录//#ifdefMPexportfunctionlogin(code,encryptedData,iv){returnrequest({url:'/youlai-auth/oauth/token',method:'post',params:{code:code,encryptedData:encryptedData,iv:iv,grant_type:'wechat'},headers:{'Authorization':'BasicbWFsbC13ZWFwcDoxMjM0NTY='//客户端信息Base64加密,明文:mall-weapp:123456}})}//#endif

设置OAuth2客户端支持wechat授权模式

3.测试

实际业务场景常用的3种授权模式也就告一段落。

但是如果你对SpringSecurityOAuth2有些了解的话,你会有疑问这些扩展的模式对应的刷新模式需不需要做什么调整呢?

如果扩展只是针对一种用户体系以及一种认证方式(用户名/手机号/openid)的话,比如验证码模式的扩展,就不需要对刷新模式做调整。

但是如果是多用户体系或者多种认证方式,youlai-mall就是多用户体系以及多种认证方式,这时你必须做些调整来适配,不过改动不大,具体为什么调整和如何调整下文细说。

五.多用户体系刷新模式

1.原理

刷新模式时序图如下,相较于密码模式还只是Granter和Provider的变动。

着重说一下刷新模式的认证提供者PreAuthenticatedAuthenticationProvider,其authenticate()认证方法只做用户状态校验,check()方法调用AccountStatusUserDetailsChecker#check(UserDetails)。

注意下this.preAuthenticatedUserDetailsService.loadUserDetails((PreAuthenticatedAuthenticationToken)authentication);的preAuthenticatedUserDetailsService用户服务。

在没有进行授权模式扩展的时候,是下面这样设置的

然后在AuthorizationServerEndpointsConfigurer#addUserDetailsService(DefaultTokenServices,UserDetailsService)构造PreAuthenticatedAuthenticationProvider里设置了UserDetailService用户服务。

这样在多用户体系认证下问题可想而知,用户分别有系统用户和会员用户,这里固定成一个用户服务肯定是行不通的,扩展授权模式创建Provider时可以指定具体的用户服务UserDetailService,就如下面这样:

你可以为每个授权模式扩展新增对应的刷新模式,但是这样的话比较麻烦,所以这里使用的另一种方案,重新设置PreAuthenticatedAuthenticationProvider的preAuthenticatedUserDetailsService属性,让其有判断选择用户体系和认证方式的能力。

2.实战

首先我们清楚一个OAuth2客户端基本对应的是一个用户体系,比如youlai-mall项目的客户端和用户体系对应关系如下表:

OAuth2客户端名称

OAuth2客户端ID

用户体系

管理系统

mall-admin-web

系统用户

H5/Android/IOS移动端

mall-app

商城会员

小程序端

mall-weapp

商城会员

那就有一个很简单有效的思路,可以在系统内部维护一个如上表的映射关系Map,然后根据传递的客户端ID去选择用户体系。

就这?当然不是,还有个点你必须要考虑到,举个例子虽然移动端的用户体系是会员用户,但是它可能有多种认证方式呀,比如可以同时支持手机短信验证码和用户名密码甚至更多的认证方式。

而SpringSecurityOAuth2默认的UserDetailsService接口只有一个loadUserByUsername()方法,很显然是做不到会员体系支持多种认证方式的。

复制代码123JAVApublicinterfaceUserDetailsService{UserDetailsloadUserByUsername(Stringvar1)throwsUsernameNotFoundException;}

所以需要在UserDetailsService的实现类新增认证方式,然后在运行时将UserDetailsService转为具体的实现类,具体可看下有来项目的MemberUserDetailsServiceImpl的实现,同时支持手机号和三方标识openid获取用户认证信息,即两种不同的认证方式。

复制代码12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273JAVA/***商城会员用户认证服务**@author<ahref="mailto:xianrui0365@163.com">xianrui</a>*/@Service("memberUserDetailsService")@RequiredArgsConstructorpublicclassMemberUserDetailsServiceImplimplementsUserDetailsService{privatefinalMemberFeignClientmemberFeignClient;@OverridepublicUserDetailsloadUserByUsername(Stringusername){returnnull;}/***手机号码认证方式**@parammobile*@return*/publicUserDetailsloadUserByMobile(Stringmobile){MemberUserDetailsuserDetails=null;Result<MemberAuthDTO>result=memberFeignClient.loadUserByMobile(mobile);if(Result.isSuccess(result)){MemberAuthDTOmember=result.getData();if(null!=member){userDetails=newMemberUserDetails(member);userDetails.setAuthenticationMethod(AuthenticationMethodEnum.MOBILE.getValue());//认证方式:OpenId}}if(userDetails==null){thrownewUsernameNotFoundException(ResultCode.USER_NOT_EXIST.getMsg());}elseif(!userDetails.isEnabled()){thrownewDisabledException("该账户已被禁用!");}elseif(!userDetails.isAccountNonLocked()){thrownewLockedException("该账号已被锁定!");}elseif(!userDetails.isAccountNonExpired()){thrownewAccountExpiredException("该账号已过期!");}returnuserDetails;}/***openid认证方式**@paramopenId*@return*/publicUserDetailsloadUserByOpenId(StringopenId){MemberUserDetailsuserDetails=null;Result<MemberAuthDTO>result=memberFeignClient.loadUserByOpenId(openId);if(Result.isSuccess(result)){MemberAuthDTOmember=result.getData();if(null!=member){userDetails=newMemberUserDetails(member);userDetails.setAuthenticationMethod(AuthenticationMethodEnum.OPENID.getValue());//认证方式:OpenId}}if(userDetails==null){thrownewUsernameNotFoundException(ResultCode.USER_NOT_EXIST.getMsg());}elseif(!userDetails.isEnabled()){thrownewDisabledException("该账户已被禁用!");}elseif(!userDetails.isAccountNonLocked()){thrownewLockedException("该账号已被锁定!");}elseif(!userDetails.isAccountNonExpired()){thrownewAccountExpiredException("该账号已过期!");}returnuserDetails;}}

新增的PreAuthenticatedUserDetailsService可根据客户端和认证方式选择UserDetailService和方法获取用户信息UserDetail

复制代码1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768JAVA/***刷新token再次认证UserDetailsService**@author<ahref="mailto:xianrui0365@163.com">xianrui</a>*@date2021/10/2*/@NoArgsConstructorpublicclassPreAuthenticatedUserDetailsService<TextendsAuthentication>implementsAuthenticationUserDetailsService<T>,InitializingBean{/***客户端ID和用户服务UserDetailService的映射**@seecom.youlai.auth.security.config.AuthorizationServerConfig#tokenServices(AuthorizationServerEndpointsConfigurer)*/privateMap<String,UserDetailsService>userDetailsServiceMap;publicPreAuthenticatedUserDetailsService(Map<String,UserDetailsService>userDetailsServiceMap){Assert.notNull(userDetailsServiceMap,"userDetailsServicecannotbenull.");this.userDetailsServiceMap=userDetailsServiceMap;}@OverridepublicvoidafterPropertiesSet()throwsException{Assert.notNull(this.userDetailsServiceMap,"UserDetailsServicemustbeset");}/***重写PreAuthenticatedAuthenticationProvider的preAuthenticatedUserDetailsService属性,可根据客户端和认证方式选择用户服务UserDetailService获取用户信息UserDetail**@paramauthentication*@return*@throwsUsernameNotFoundException*/@OverridepublicUserDetailsloadUserDetails(Tauthentication)throwsUsernameNotFoundException{StringclientId=RequestUtils.getOAuth2ClientId();//获取认证方式,默认是用户名usernameAuthenticationMethodEnumauthenticationMethodEnum=AuthenticationMethodEnum.getByValue(RequestUtils.getAuthenticationMethod());UserDetailsServiceuserDetailsService=userDetailsServiceMap.get(clientId);if(clientId.equals(SecurityConstants.APP_CLIENT_ID)){//移动端的用户体系是会员,认证方式是通过手机号mobile认证MemberUserDetailsServiceImplmemberUserDetailsService=(MemberUserDetailsServiceImpl)userDetailsService;switch(authenticationMethodEnum){caseMOBILE:returnmemberUserDetailsService.loadUserByMobile(authentication.getName());default:returnmemberUserDetailsService.loadUserByUsername(authentication.getName());}}elseif(clientId.equals(SecurityConstants.WEAPP_CLIENT_ID)){//小程序的用户体系是会员,returnmemberUserDetailsService.loadUserByOpenId(authentication.getName());default:returnmemberUserDetailsService.loadUserByUsername(authentication.getName());}}elseif(clientId.equals(SecurityConstants.ADMIN_CLIENT_ID)){//管理系统的用户体系是系统用户,认证方式通过用户名username认证switch(authenticationMethodEnum){default:returnuserDetailsService.loadUserByUsername(authentication.getName());}}else{returnuserDetailsService.loadUserByUsername(authentication.getName());}}}

AuthorizationServerConfig配置重新设置PreAuthenticatedAuthenticationProvider的preAuthenticatedUserDetailsService属性值

复制代码1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071JAVA/***配置授权以及令牌的访问端点和令牌服务(tokenservices)*/@Overridepublicvoidconfigure(AuthorizationServerEndpointsConfigurerendpoints){//Token增强TokenEnhancerChaintokenEnhancerChain=newTokenEnhancerChain();List<TokenEnhancer>tokenEnhancers=newArrayList<>();tokenEnhancers.add(tokenEnhancer());tokenEnhancers.add(jwtAccessTokenConverter());tokenEnhancerChain.setTokenEnhancers(tokenEnhancers);//获取原有默认授权模式(授权码模式、密码模式、客户端模式、简化模式)的授权者List<TokenGranter>granterList=newArrayList<>(Arrays.asList(endpoints.getTokenGranter()));//添加验证码授权模式授权者granterList.add(newCaptchaTokenGranter(endpoints.getTokenServices(),endpoints.getClientDetailsService(),endpoints.getOAuth2RequestFactory(),authenticationManager,stringRedisTemplate));//添加手机短信验证码授权模式的授权者granterList.add(newSmsCodeTokenGranter(endpoints.getTokenServices(),endpoints.getClientDetailsService(),endpoints.getOAuth2RequestFactory(),endpoints.getClientDetailsService(),endpoints.getOAuth2RequestFactory(),authenticationManager));CompositeTokenGrantercompositeTokenGranter=newCompositeTokenGranter(granterList);endpoints.authenticationManager(authenticationManager).accessTokenConverter(jwtAccessTokenConverter()).tokenEnhancer(tokenEnhancerChain).tokenGranter(compositeTokenGranter)/**refreshtoken有两种使用方式:重复使用(true)、非重复使用(false),默认为true*1重复使用:accesstoken过期刷新时,refreshtoken过期时间未改变,仍以初次生成的时间为准*2非重复使用:accesstoken过期刷新时,refreshtoken过期时间延续,在refreshtoken有效期内刷新便永不失效达到无需再次登录的目的*/.reuseRefreshTokens(true).tokenServices(tokenServices(endpoints));}publicDefaultTokenServicestokenServices(AuthorizationServerEndpointsConfigurerendpoints){TokenEnhancerChaintokenEnhancerChain=newTokenEnhancerChain();List<TokenEnhancer>tokenEnhancers=newArrayList<>();tokenEnhancers.add(tokenEnhancer());tokenEnhancers.add(jwtAccessTokenConverter());tokenEnhancerChain.setTokenEnhancers(tokenEnhancers);DefaultTokenServicestokenServices=newDefaultTokenServices();tokenServices.setTokenStore(endpoints.getTokenStore());tokenServices.setSupportRefreshToken(true);tokenServices.setClientDetailsService(clientDetailsService);tokenServices.setTokenEnhancer(tokenEnhancerChain);//多用户体系下,刷新token再次认证客户端ID和UserDetailService的映射MapMap<String,UserDetailsService>clientUserDetailsServiceMap=newHashMap<>();clientUserDetailsServiceMap.put(SecurityConstants.ADMIN_CLIENT_ID,sysUserDetailsService);//管理系统客户端clientUserDetailsServiceMap.put(SecurityConstants.APP_CLIENT_ID,memberUserDetailsService);//Android/IOS/H5移动客户端clientUserDetailsServiceMap.put(SecurityConstants.WEAPP_CLIENT_ID,

核心代码基本都在上面,在完成以上的调整之后刷新模式就可以了,接下来对新扩展的授权模式对应的刷新模式进行逐一测试。

3.测试

3.1Postman导入cURL操作说明

下面所有的测试都会把cURL贴出来,至于为什么强调这个?原来以为我把用Postman测试SpringSecurityOAuth2获取token的完整请求截图放入项目说明文档README.md这样就不会再有人问登录接口403报错,但事实反馈确实自己挺失望,以致于后来再有这样的问题基本上选择沉默了,希望大家换位思考理解下。所以这次想到的方案是把接口信息以cURL的形式贴出来,然后直接导入Postman测试。

下面是有来项目获取token的cURL

复制代码12SHELLcurl--location--requestPOST':9999/youlai-auth/oauth/token?username=admin&password=123456&grant_type=password'\--header'Authorization:BasicbWFsbC1hZG1pbi13ZWI6MTIzNDU2'

进入Postman选择File→Import→Rawtext把上面的cURL导入

3.2密码模式测试

密码模式的测试使用的客户端信息,客户端ID:客户端密钥:mall-admin-web:123456-----Base64在线编码→bWFsbC1hZG1pbi13ZWI6MTIzNDU2

如果你要更改客户端,请在下方接口的请求头Authorization更换客户端信息即可,不然会报403提示,因为你的客户端信息不正确认证不成功禁止访问。

有些人会问现在有来项目没有自定义客户端认证异常的处理,其实在我之前的文章有提供解决方案客户端认证异常,有需要的可以根据文章调整。至于为什么项目中没有使用方案,首先觉得实现比较复杂,如果你有好的解决方案欢迎提出,另外这种客户端信息错误作为一个开发人员来说你是完全可以规避的。

获取token

复制代码12SHELLcurl--location--requestPOST':9999/youlai-auth/oauth/token?username=admin&password=123456&grant_type=password'\--header'Authorization:BasicbWFsbC1hZG1pbi13ZWI6MTIzNDU2'

刷新token

refresh_token需要替换,在第一步获取token返回的refresh_token

复制代码12SHELLcurl--location--requestPOST':9999/youlai-auth/oauth/token?BasicbWFsbC1hZG1pbi13ZWI6MTIzNDU2'

3.3验证码模式测试

验证码模式的测试使用客户端的信息,客户端ID:客户端密钥:mall-admin-web:123456-----Base64在线编码→bWFsbC1hZG1pbi13ZWI6MTIzNDU2

获取token

复制代码12SHELLcurl--location--requestPOST':9999/youlai-auth/oauth/token?username=admin&password=123456&grant_type=captcha&uuid=11add22b38e74a57bade0bf628a70645&validateCode=1'\--header'Authorization:BasicbWFsbC1hZG1pbi13ZWI6MTIzNDU2

刷新token

复制代码12SHELLcurl--location--requestPOST':9999/youlai-auth/oauth/token?BasicbWFsbC1hZG1pbi13ZWI6MTIzNDU2'

3.4手机短信验证码测试

手机短信验证码模式测试使用的客户端的信息,客户端ID:客户端密钥:mall-app:123456-----Base64在线编码→bWFsbC1hZG1pbi13ZWI6MTIzNDU2

获取token

复制代码12SHELLcurl--location--requestPOST':9999/youlai-auth/oauth/token?mobile=17621590365&code=666666&grant_type=sms_code'\--header'Authorization:BasicbWFsbC1hcHA6MTIzNDU2'

刷新token

复制代码12SHELLcurl--location--requestPOST':9999/youlai-auth/oauth/token?BasicbWFsbC1hcHA6MTIzNDU2'

客户端ID:客户端密钥:mall-weapp:123456-----Base64在线编码→bWFsbC13ZWFwcDoxMjM0NTY=

获取token

复制代码12SHELLcurl--location--requestPOST':9999/youlai-auth/oauth/token?code=063hEOFa1N1dWB0XpRIa1WvNw74hEOF-&encryptedData=1qmFeCKbTxZyCdzctu37sX+jOnM9dZG9lKyD3v6FhA5sCEtDwaF/wqyVR70QVrqt7bGVH+Kb+PBsFJlBXUdjnFGlrwmPqgNusI4f5eA8SvZgopvmlzJhXwe+OjLCQooeGnSkcnUrUuMA/G4ZYWFeljaHhxJq/75APWs4HyLANfbeLp50qI9xrRJVUXlTqdqJ0ub38ZxWVvWZMqY8FaskAiZpxzrF30eXu93BCpDavRCVzlSfv6LFJmmvEGVOKr4Wap9ND82N3sDMyArRsdhdhmoWIYBbRs+iLbKcS4WyOhpmaQr4fhhOuxO+zSAa7W+eNmCH2Id6Pgpvhl6ureNNzEb0cQLoksP6oakPmv/yEiw5fnW6Oi9jJbxzlMyORN3/atHgBl6zLIgS9UMhFE+42Vp5B3L8jLly4+B4NpNgol+khXoh+ycUXSRPV4bUuriv&iv=j+brWSrqRW+d4lAjRWW4RA==&grant_type=wechat'\--header'Authorization:BasicbWFsbC13ZWFwcDoxMjM0NTY='

刷新token

六.总结

本篇基于SpringSecurityOAuth2扩展了实际开发常用的验证码模式、同时稍调整刷新模式使其能够适配扩展的几种模式以及多用户体系。通过授权模式的扩展揭露SpringSecurityOAuth2的认证流程和底层原理,相信对流程和原理有个清晰的思路之后,不同的认证需求都可以做到得心应手。最后还是感叹下Spring框架的魅力,就是你能感受到它在功能的实现的基础上会给你留个扩展的入口,而不是让你想着去改它的源码去实现。最后希望大家都能收获些东西吧,虽然咱这也不图啥,写这些说实话对自己提升也不大,算是自己的一份心血,也不希望白费了。

佳能镜头鱼眼设置在哪里

-进入鱼眼拍摄模式:在菜单设置中选择鱼眼拍摄模式,开启鱼眼模式。

佳能EF8-15mmf/4LUSM鱼眼镜头在不同焦距时的圆形鱼眼效果

佳能EF8-15mmf/4LUSM鱼眼镜头在不同焦距时的对角线鱼眼效果

该镜头虽然已停产,但在各类电商平台上仍有全新镜头在售,售价约为3700元,性价比略优。

佳能800D价格大概在4500块左右;77D价格大概在8000左右,80D10000左右,5D等或者更高级都可以。为什么说佳能,因为我用的是佳能,用的还顺手,其他的品牌没用过,不好评价。

这款16mm手动对焦鱼眼镜头的体积比上述的适马镜头更加小巧,有尼康、佳能与M42mm螺口卡口。如果购买时再多加150元,还能增添带对焦提示音电路的款式。该鱼眼镜头在成像素质方面具有色彩浓厚、立体感强的特点,在锐度、解像力、反差、色彩还原方面不输佳能或尼康原厂镜头。全套购置的花费仅为1600元,性价比极高。

1.镜头的安装

在安装鱼眼镜头时,一定要注意镜头的定位。鱼眼镜头是一个弯曲的圆柱形,因此必须正确地安装在相机上,以确保图像呈现出正确的曲线。

2.镜头的曲率

鱼眼镜头有着非常大的曲率,这意味着镜头的曲率半径越小,所捕捉到的场景视角越大。佳能相机鱼眼镜头通常拥有曲率半径为10mm到20mm的范围。

3.镜头的对焦

由于鱼眼镜头具有非常大的视角,图像通常都是非常宽广的,因此焦距也非常重要。在使用佳能相机鱼眼镜头时,焦距非常短,所以您需要非常小心地对焦,确保您的主题位于光圈的中心位置。

4.镜头的光圈

镜头的光圈大小对图像的亮度和景深都有很大的影响。在使用佳能相机鱼眼镜头时,鱼眼镜头的光圈通常很小,为f/4到f/5.6之间。这意味着您可能需要使用较长的曝光时间来获取正确的曝光,或者开启相机的高ISO设置。

佳能镜头三码不合

相机和镜头都是有唯一编号的。相机出厂时是不交关税的。只有进口到大陆才交

水货有序列号只是三码不能合一。香港是是有免税的商场,但是大陆没有,你带回来也不会给你质保的,除非你买的是行货!

你说的这个绝对是山寨我朋友被骗过,客服说的和你这里说的一样,典型的山寨机就是一个佳能的智能小单反1100

相机和镜头都是有唯一编号的。相机出厂时是不交关税的。只有进口到大陆才交。我买的行货机上面直接有查询真伪的查询码,水货感觉序列号应该也可以吧,怎么说也是香港出售的

如果你是在淘宝买的相机的话,很有可能买到翻新的相机!

行货水货都是正品。查不着就是水货。水货不是假的,是不保的。

什么是佳能镜头三码?

佳能镜头三码是指佳能公司制造的每个镜头都有三个辨识度高且唯一的编码:

1.序列号:唯一且不会重复的数字编码,每个镜头都有自己独特的序列号。

2.生产日期:年月日的编码,记录了该镜头的生产日期。

3.镜头型号:也就是镜头的名称和型号,比如EF100mmf/2.8LMacroISUSM。

那如何验证佳能镜头的三码合一呢?

伪造佳能镜头需要同时伪造三个编码,因此我们需要确认这三个编码是否合一:

1.序列号:每款佳能镜头都带有一个唯一的序列号,用户可通过佳能官网或其他认证渠道查询序列号是否真实,来确保镜头的真伪。

2.生产日期:佳能镜头的生产日期在序列号中留下痕迹,我们可以查询佳能官网中该型号镜头的生产版本以及生产批次,来确定生产日期的真实性。

3.镜头型号:每款佳能镜头都有独特的型号,我们可以通过佳能官网或其他认证渠道查询该型号的详细参数和特点,来核实镜头型号是否匹配。

尼康d5300镜头锁在哪里

了解80D的镜头锁位置是非常重要的,它能够确保你的镜头牢固地与相机连接在一起,避免在拍摄过程中产生意外的摇晃或者意外脱落。80D的镜头锁在哪儿呢?

我们需要先寻找到80D镜头锁的位置。一般而言,80D的镜头锁位于镜头底部。这个锁是一个小的开关,可以在镜头上轻松找到。当你找到它之后,你需要将它向上或向下移动,来开启或关闭镜头锁。一旦锁定,镜头就会安全地固定在相机上,确保稳定和安全的拍摄。

镜头锁的目的主要是为了确保镜头在拍摄过程中保持稳定,防止意外移动或脱落。这对于拍摄高质量的照片和视频非常重要,特别是在使用较长焦距或重型镜头时。

镜头为什么转不动啊?确实是推拉的,但推不动也拉不动,纹丝不动。锁在哪里啊?

技术亮点

1.无光学低通滤镜2416万有效像素DX格式CMOS传感器

D5300搭载2416万有效像素DX格式CMOS传感器。提供从ISO100到ISO12800的标准感光度范围,上限比D5200更高。此外该传感器采用无低通滤镜设计可充分发挥相机高像素的优势。

那么这样看来D5300就是采用D7100的传感器?先不谈新闻稿中“尼康独自开发”是否可靠,就传感器的外貌,D5300与D7100、D5200、D3200均不相同。我们可在官方资料中找到传感器的图片,将几种传感器放在一起就会发现他们封装风格并不相同。

四块CMOS对比

chipworks拆解过D3200、D5200,前者为尼康设计瑞萨制造,后者则是东芝生产的。D7100的传感器可以视为D5200的无低通版。那么问题来了,D5300的传感器出自哪里?目前还没有拆解证实这一点,对于普通消费者来说不必过分纠结于此。

D5300支持14bit/12bit。D5200仅支持14bit

2.EXPEED4图像处理器

尼康D5300是首款搭载EXPEED4图像处理器的尼康数码相机,具备更快速的处理能力,优化数码单反相机性能,提供更优异的降噪效果、自动白平衡、色彩还原以及色调处理。

返回顶部