在职加薪基础项目-归档第16天-讲义spring security oauth2v_第1页
在职加薪基础项目-归档第16天-讲义spring security oauth2v_第2页
在职加薪基础项目-归档第16天-讲义spring security oauth2v_第3页
在职加薪基础项目-归档第16天-讲义spring security oauth2v_第4页
在职加薪基础项目-归档第16天-讲义spring security oauth2v_第5页
免费预览已结束,剩余35页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

学成-第16天-讲义-SpringSecurityOauth2用户认证需求截至目前,项目已经完成了学习功能,用户通过学习页面点播进行学习。如何去记录学生的学习过程呢?要想掌握学生的学习情况就需要知道用户的,记录哪个用户在什么时间学习什么课程;如果用户要购买课程也需要知道用户的。所以,去管理学生的学习过程最基本的要实现用户的认证。用户认证通过后去系统的资源,系统会判断用户是否拥有资源的权限,只允许限的系统资源,限的资源将无法,这个过程叫用户。本项目包括多个子项目,如:学习系统,教学、系统等,为了提高用户体验性需要实现用户只证一次便可以在多个拥有权限的系统中,这个功能叫做单点登录。百科:单点登录(SingleSignOn 简称为SSO,是目前比较流行的企业业务整合的解决方案之一。下图是SSO的示意图,用户登录学成网一次即可多个系统1.31.3 不属于本系统,本系统并没有用户的账号、等信息,本系统如果要获取该用户的基本信息则需要首先通 的认证系统 认证)进行认证 认证通过后本系统便可获取 用户基本信息,从而在本系统将 用户的头像、昵称等信息显示出来,该用户便不用在本系统却可以直接学习什么是第认证(跨平台认证 用户认证技术单点登录的特点1、ApacheShiro.2、3、SpringsecurityOauth2Oauth2认证流第认证技术方案最主要是解决认证协议的通用标准问题,因为要实现跨系统认证,各系统之间要遵循一定的AUH协议为用户资源的提供了一个安全的、开放而又简易的标准。同时,任何第都可以使用AU认证服务,任何服务提供商都可以实现自身的AUH认证服务,因而AUH是开放的。业界提供了AUH现如PP、JavScip,Java,Ry等各种语言开发包,大大节约了程序员的时间,因而AUH是简易的。互联网很多服务如OpnAP,很多大公司如,aho,等都提供了AUH认证服务,这些都足以说明AUH标准逐渐成为开放资源的标准。Oath协议目前发展到.版本,.0版本过于复杂,2.版本已得到广泛应用。参考:tts /ite/At/ fr=ladinOauth协议 认证的过程1、客户端请求用户进入程序的登录页面,点 的图标 里信息的资源拥有者点击 ,此时用户扫 会对资源拥有者的进行验证,验证通过后,微信会询问用户是否给程序员自己的 颁发一个码,并重定向到程序员的。3、客户端获取到码,请求认证服务器申请令认证服务器验证了客户端请求的码,如果合法则给客户端颁发令牌,令牌是客户端资源的通行证此交互过程用户看不到,当客户端拿到令牌后,用户在程序员看到已经登录成功。客户端携带令牌资源服务器的资源程序员携带令牌请求服务器获取用户的基本信息服务器来校验令牌的。引自Oauth2.0协议rfc6749 学成Androd客户端、学成在 3、服务器(也称认证服务器用来对资源拥有的进行认证、对资源进行。客户端要想资源需要通过认证服务器由资源拥有者权后方可。资源的服务器,比如,学成网用户管理服务器了学成网的用户信息,学成网学习服务器了学生的学信息, 的资源服务了 的用户信息等。客户端最终资源服务器获取资源信息。Oauth2在本项目的应Oath2是一个标准的开放的协议,应用程序可以根据自己的要求去使用Oauth2,本项目使用Oauth2下目标:3、学成前端(客户端)学成微服务的资源SpringsecurityOauth2本项目采用Springsecurity+Oauth2完成用户认证及用户,Springsecurity是一个强大的和高度可定制的身份验证和控制框架,Springsecurity框架集成了Oauth2协议,下图是项目认证架构图:2、认证服务下发用户令牌,拥有令牌表示合法 如果合法则放行继续6、资源服务完成则响应资源信息SpringSecurityOauth2本项目认证服务基于SpringSecurityOauth2进行构建,并在其基础上作了一些扩展,采用JWT令牌机制,并自定义了用户的内容。本的主要目标是学项目中集成SpringSecurityOauth2的方法和流程,通过springSecurityOauth2的研究需要达到以下目标:2、理解springSecurityOauth23、掌握资源服务集成 导入基础工 下的xc-service-ucenter-auth工程,该工程是基于SpringSecurityOauth2的一个二次封装的工创建数据导入资 下的xc_user.sql,创建用户数据以“oauth_”开头的表都是springSecurity自带的本项目中springSecurity主要使用oauth_client_detailsclient_id:客户端idresource_ids:资源id(暂时不用)client_secret:客户端scope:范围authorized_grant_type:类型Oauth2模码模式(AuthorizationCode)隐式模式(Implicit)模式(ResourceOwnerPasswordCredentials)客户端模式(ClientCredentials)其中码模式和模式应用较多,本小节介绍码模式码流 认证的过程就是码模式,流程如下1、客户端请求第2、用户(资源拥有者)同意给客户端3、客户端获取到码,请求认证服务器申请令牌4、认证服务器向客户端响应令牌5、客户端请求资源服务器的资源 资源服务校验令牌,完成申请请求认证服务获取码参数列表如下response_type:码模式固定为scop:客户端范围,和配置类中设置的scop一致首先跳转到登录页面SngSecuty接收到请求会调用UsrDtisService接口的laUsrByUsr方法查询用户正确的。当前导入的基础工程中将正确的硬编码为“123,所以这里账号随意输入,输入12即可认证通过。认证服务携带码跳转申请令拿到码后,申请令牌Post请求:hos参数如下erct_i:申请码时的跳转ul,一定和申请码时用的riec_ui一致。此需使用pBsc认。什么是httpBasicttp协议定义的一种认证方式,将客户端id和客户端按照客户端D:客户端”的格式拼接,并用ase64编码,放在heaer中请求服务端,一个例子:Authorization:Basic认证失败服务端返回401Unauthorizedhttpbasic点击发送申请令牌成功token_type:有MACToken与BearerToken两种类型,两种的校验算法不同,RFC6750建议Oauth2采用Bearer 资源服资源服务流 客户端携带令牌资源服务,如果令牌合法则可成功资源服务中的资上图的业务流程如下3、客户端携带令牌资源服客户端在Httpheader中添加:Authorization:Bearer资源服务接收到令牌,使用公钥校验令牌的资源服务配基本上所有微服务都是资源服务,这里我们在课程管理服务上配置控制,当配置了控制后如要课程信1、配置公 对外向资源服务提供公钥,资源服务使用公钥来校验令牌的。 2、添加依<groupId>org.spri<artifactId>spring‐c@EnableGlobalMethodSecurity(prePostEnabled=true,securedEnabled=true)//激活方法上PreAuthorize注publicclassResourceServerConfigextendsResourceServerConfigurerAdapter//privatestaticfinalStringPUBLIC_KEY=publicTokenStoretokenStore(JwtAccessTokenConverter{returnnew}publicJwtAccessTokenConverter{JwtAccessTokenConverterconverter=newJwtAccessTokenConverter();return}获取非对称加密公钥@return公钥privateStringgetPubKey()Resourceresource=newClassPathResource(PUBLIC_KEY);try{InputStreamReaderinputStreamReader=newBufferedReaderbr=newBufferedReder(inputStreamReader);returnbr.lines().collect(Collectors.joining("\n");}catch(IOException{return}}//Http安全配置,对每个到达系统的ttp请 进行校publicvoidconfigure(HttpSecurityhttp)throwsException//所有请求必须认证通}}资源服务测这里我们测试课程查get{{"error":"error_description":"Fullauthenticationisrequiredtoaccessthis}请求时携带令牌在httpheader中添加Authorization:Bearer解决swagger-ui当课程管理加了之后再swagger-ui则报错修改配置类ResorceSevrCnfig的cnfigre方法:针对swagr-i的请求路径进行放行://Http//Http安全配置,对每个到达系统的http请 进行校publicvoidconfigure(HttpSecurityhttp)throwsException//所有请求必须认证通//下边的路径.antMatchers("/v2/api‐docs","/swagger‐resurces/cofiguration/ui","/swagger‐resources","/swagger‐resources/configuration/ecurity","/swagger‐}注意通过上边的配置虽然可以swgr-i,但是无法进行单元测试,除非去掉认证的配置或在上边配置中添加所有请求均放行("/**")。3.43.4模式(ResourceOwnerPasswordCredentials)与码模式的区别是申请令牌不再使用码,而是直接并且此需要使用httpBasic认证上边参数使用x-www-form-urlencoded方式传输,使用postmanSpringSecurityOauth2提供校验令牌的端Get:参数token使用postman结果如下{{"companyId":"userpic":null,"user_name":"mrt","scope":["name":"utype":"id": "jti":"client_id":}exp:过期时间,long类型,距离1970年的秒数(newDate().getTime()可得到当前时间距离1970年的毫秒数)。user_name:用户名client_id:客户端Id,在oath_client_details中配置scope:客户端范围在oauth_client_details表中配置 、ameutype、id:这些字段是本认证服务在SpringSecurity基础上扩展的用户刷新令牌是当令牌快过期时重新生成一个令牌,它于码和生成令牌不同,刷新令牌不需要码也不需要账号和,只需要一个刷新令牌、客户端i和客户端。测试如下:grant_type:固定为JWTJWT问题传统方法的问题是用户每次请求资源服务,资源服务都需要携带令牌认证服务去校验令牌的,并据令牌获取用户的相关信息,性能低下。解决什么是JSONebon(JWT)是一个开放的行业标准(RFC7519),它定义了一种简介的、自包含的协议格式,用于在通信双方传递json对象,传递的信息经过数字签名可以被验证和信任。JWT可以使用HMC算法或使用SA的公钥/私钥对来签名,防止被篡改。标准:1、JWT令牌较长,占空间比较大头部包括令牌的类型(即JWT)及使用的哈希算法(如HMACSHA256或RSA){{"alg":"typ":}第二部分是负载,内容也是一个js对象,它是存放有效信息的地方,它可以存放jw提供的现成字段,比如:iss(签发者),xp(过期时间戳),su(面向的用户)等,也可自定义字段。最后将第二部分负载使用Base64Ur编码,得到一个字符串就是JWT令牌的第二部分。{{"sub": "name":456","admin":tue}这个部分使用ase4rl将前两部分进行编码,编码后使用点()连接组成字符串,最后使用hadr中签名算法进行签名。一个例子base64UrlEncode(header)+"."+base64UrlEncode(header):jwt令牌的第一部分。base64UrlEncode(payload):jwt令牌的第二部分。JWTSpringSecurity提供对JWT的支持,本节我们使用SpringSecurity提供的wHlr来创建JWT令牌,校验JWT令牌下边命令生成密钥,采用RSA算法每个包含公钥和私keytool-genkeypair-aliasxckey-keyalgRSA-keypassxuecheng-keystorexc.keystore-storepassKeytool是一个java提供的管理工-keypass:密钥查询信息keytool-list-keystorxc.keyst删除keytool-delete-aliasxckey-keystore2、导出公安 安装资 keytoolkeytool‐list‐rfc‐‐keystorexc.keystore|opensslx509‐informpem下边这一段就是公钥内容-----BEGINPUBLICKEY----- PgLnbQczBHbBug6uOr78qnWsYxHlW6Aa5dI5NsmOD4DLtSw8eX0hFyK5Fmz2yMJePDqUi0JYS2r0iIo7n8vN7s83v5uOQIDAQAB-----ENDPUBLICKEY-----生成jwt令publicvoid 文Stringkey_location=//密钥Stringkeystore_password= 路ClassPathResourceresource=new//密钥工KeyStoreKeyFactorykeyStoreKeyFactory=newKeyStoreKeyFactory(resource,//密钥 , 和别名要匹StringStringkeypassword=//Stringalias=//密钥对(密钥和公钥KeyPairkeyPair=RSAPrivateKeyaPrivate=(RSAPrivateKey)Map<String,Object>tokenMap=newHashMap<>();tokenMap.put("id","123");tokenMap.put("name",tokenMap.put("roles",tokenMap.put("ext",//生成jwtJwtjwt=JwtHelper.encode(JSON.toJSONString(tokenMap),new//取出jwtStringtoken=jwt.getEncoded();}验证jwt令////资源服务使用公钥验证jwt ,并对publicvoidStringtoken48pJB5f‐le2zgYMqR1L2LyTmrbRdRxkrQfsa1j8IW2T4eUiN3f9wF9JxUK1//Stringpublicky="‐‐‐‐‐BEGINPUBLIC OQIDAQAB‐‐‐‐‐ENDPUBLICKEY‐‐‐‐‐";//校验Jwtjwt=JwtHelper.decodeAndVerify(token,new//获取jwt原始Stringclaims=//jwt令Stringencoded=jwt.getEncoded();}认证接口开用户登录的流程执行流程 、由于jwt令牌过长,不宜在 中,所以将jt令牌在i,由客户端请求服务端获取并在客户端存储。Redis配安装1、安装Redis服 redis‐serverredis‐server出现下图说明redisredis‐serverredis‐server‐‐service‐installredis.windows‐service.conf‐‐loglevel 卸载服务:redis-server.exe--service-开启服务:redis-server.exe--service-停止服务:redis-server.exe--service-2、redis-desktop- 连接成功redis连接配name:host:${REDIS_HOST:}port:${REDIS_PORT:6379}timeout:5000#连接超时毫秒maxActive:maxIdle:minIdle:maxWait:‐1#连接池最大等行时间‐1没有限制测publicclassRedisTest{privateStringRedisTemplatestringRedisTemplate;publicvoid//定义Stringkey=//定义Map<String,String>mapValue=newHashMap<>(); Stringvalue=//向redis 字符stringRedisTemplate.boundValueOps(key).set(value,60, 过期时间,已过期返回Longexpire=//根据key获取Strings=stringRedisTemplate.opsForValue().get(key);}}需求分认证服务需要实现的功能如1、登录接前端pst提交账号、等,用户校验通过,生成令牌,并将令牌到i。将令牌写入。2、退出接删除中的令牌业务流程如下Api接@Api(value="@Api(value="用户认证",description="用户认证接口")publicinterfaceAuthControllerApi{@ApiOperation("登录publicLoginResultlogin(LoginRequest@ApiOperation("退出publicResponseResult}配置参在application.ymltokenValiditySeconds:1200 到redis的过期时clientId:XcWebAppclientSecret:XcWebApp:MaxAge:申请令牌测为了不破坏SigSecuity的代码,我们在Sric方法中通过Rstemlat请求SpngSecuiy所的申请令牌接口来申请令牌,下边是测试代码:publicclassTestClient{LoadBalancerClientRestTemplatepublicvoid//采用客户端负载均衡,从eureka获取认证服务的ip和端ServiceInstanceserviceInstance=URIuri=StringauthUrl=//URIurl,HttpMethodmethod,HttpEntity<?>requestEntity,Class<T>//url就是申请令牌的url//methodhttp的方法类//requestEntity//responseType,将响应的结果生成的类//请求的内容//1、header信息,包括了httpbasicMultiValueMap<String,String>headers=newLinkedMultiValueMap<String,String>();Stringhttpbasic=httpbasic("XcWebApp","XcWebApp");//"Basicheaders.add("Authorization",//2、包括:grant_type、username、MultiValueMap<String,String>body=newLinkedMultiValueMap<String,String>(); HttpEntity<MultiValueMap<String,String>>multiValueMapHttpEntity=newHttpEntity<MultiValueMap<String,String>>(body,headers);//指 restTemplate当遇到400或401响应时候也不要抛出异常,也要正常返回restTemplate.setErrorHandler(newDefaultResponspublicvoidhandleError(ClientHttpRespnseesponse)throwsIOException//当响应的值为400或401时候也要正常响应,不要抛出异if(response.getRawStatusCode()!=400&&respnsegetRawStatusCode()!=401){}} 调用申请令ResponseEntity<Map>exchange=restTemplate.exchange(authUrl,HttpMethod.POST,multiValueMapHttpEntity,Map.class);Mapbody1=exchange.getBody();}privateStringhttpbasic(StringclientId,String//将客户端id和客户 拼接,按“客户端id:客户 Stringstring=//进行base64编byte[]encode=Base64.encode(string.getBytes());return"Basic"+newString(encode);}}调用认证服务申请令牌,并将令牌到redis。创建AuthToken模型类,申请的令牌,包括令牌、刷新令牌、jwt令牌publicclassAuthToken{Stringaccess_token;//tokenStringrefresh_token;//刷新tokenStringjwt_token;//jwt令牌}publicclassAuthServiceprivatestaticfinalLoggerLOGGER=LoggerFactory.getLogger(AuthService.class);intRestTemplaterestTemplate;LoadBalancerClientloadBalancerClient;StringRedisTemplate//认证方publicAuthTokenlogin(Stringusername,Stringpassword,StringclientId,String//申请令AuthTokenauthToken=applyToken(username,password,clientId,clientSecret);if(authToken==null){}//将 到Stringaccess_token=authToken.getAccess_token();Stringcontent=JSON.toJSONString(authToken);booleansaveTokenResult=saveToken(access_token,content,}return} 令牌到privatebooleansaveToken(Stringaccess_token,Stringcontent,long//令牌名Stringname="user_token:"+//保存到令牌到 //获取过期时Longexpire=stringRedisTemplate.getExpire(name);returnexpire>0;}//认证方privateAuthTokenapplyToken(Stringusername,Stringpassword,StringclientId,String//选中认证服务的地ServiceInstanceserviceInstance=if(serviceInstance=={LOGGER.error("chooseanauthinstancefai}//获取令牌的Stringpath=serviceInstance.getUri().toStrng()+//定义MultiValueMap<String,String>formData=new 方formData.add("grant_type",formData.add("password",//定义MultiValueMap<String,String>header=newLinkedMultiValueMap<>();header.add("Authorization",httpbasic(clientId,clientSecret));//指 restTemplate当遇到400或401响应时候也不要抛出异常,也要正常返回restTemplate.setErrorHandler(newpublicvoidhandleError(ClientHttpResponseresponse)throwsIOException//当响应的值为400或401时候也要正常响应,不要抛出异if(response.getRawStatusCode()!=400&&response.getRawStatusCode()!=401){}}Mapmap=null;try{//http请求springsecurity的申请令牌接ResponseEntity<Map>mapResponseEntity=restTemplate.exchange(path,newHttpEntity<MultiValueMap<String,String>>(formData,header),Map.class);map=mapResponseEntity.getBody();newHttpEntity<MultiValueMap<String,String>>(formData,header),Map.class);map=mapResponseEntity.getBody();}catch(RestClientException{LOGGER.error("requestoauth_token_passworderror:{}",e.getMessage());}if(map==nullmap.get("access_token")==null||map.get("refresh_token")==null||map.get("jti")==null){//jti是jwt令牌的唯一标识作为用 令}Auth

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论