保健励志美文体育育儿作文
投稿投诉
作文动态
热点娱乐
育儿情感
教程科技
体育养生
教案探索
美文旅游
财经日志
励志范文
论文时尚
保健游戏
护肤业界

干货SpringBootSpringSecurityJwt权

  1。整体逻辑1。SpringSecurity认证的逻辑规则
  启动项目时,SpringBoot自动检索所有带Configuration的注解,所以就将我们的WebSecurityConfig给加载了,这个config中,我们需要在configure(AuthenticationManagerBuilderauth)方法中注册一个继承自UserDetailsService的接口,这个接口中只有一个方法,那就是使用username获取到数据库中用户信息并返回成UserDetail实体。这个方法需要我们按照我们的不同业务场景重写
  WebSecurityConfigdescription:author:coderymycreate:2020100113:54p1。创建WebSecurityConfig类继承WebSecurityConfigurerAdapter2。类上加上EnableWebSecurity,注解中包括Configuration注解pWebSecurityConfigurerAdapter声明了一些默认的安全特性(1)验证所有的请求(2)可以使用springSecurity默认的表单页面进行验证登录(3)允许用户使用http请求进行验证如何自定义认证1。实现并重写configure(HttpSecurityhttp)方法,鉴权,也就是判断该用户是否有访问该api的权限pp页面显示403错误,表示该用户授权失败(401代表该用户认证失败)前端可以使用返回的状态码来标识如何给用户展示用2XX表示本次操作成功,用4XX表示是客户端导致的失败,用5XX表示是服务器引起的错误EnableWebSecuritypublicclassWebSecurityConfigextendsWebSecurityConfigurerAdapter{publicstaticvoidmain(String〔〕args){BCryptPasswordEncoderpasswordEncodernewBCryptPasswordEncoder();StringencodepasswordEncoder。encode(123);System。out。println(encode);}BeanOverridepublicAuthenticationManagerauthenticationManagerBean()throwsException{AuthenticationManagermanagersuper。authenticationManagerBean();returnmanager;}SpringSecurity5。X要求必须指定密码加密方式,否则会在请求认证的时候报错同样的,如果指定了加密方式,就必须您的密码在数据库中存储的是加密后的,才能比对成功returnBeanpublicBCryptPasswordEncoderpasswordEncoder(){returnnewBCryptPasswordEncoder();}鉴权Overrideprotectedvoidconfigure(HttpSecurityhttp)throwsException{1。HttpSecurity被声明为链式调用其中配置方法包括1。authorizeRequests()url拦截配置2。formLogin()表单验证3。httpBasic()表单验证4。csrf()提供的跨站请求伪造防护功能2。authorizeRequests目的是指定url进行拦截的,也就是默认这个url是也就是所有的anyanyRequest()、antMatchers()和regexMatchers()三种方法来拼配系统的url。并指定安全策略http。authorizeRequests()这里指定什么样的接口地址的请求,需要什么样的权限ANT模式的URL匹配器。antMatchers(select)。hasRole(USER)用户可以有查询权限。antMatchers(insert)。hasRole(ADMIN)管理员可以有插入权限权限。antMatchers(empower)。hasRole(SUPERADMIN)超级管理员才有赋权的权限。antMatchers(login)。permitAll()标识list所有权限都可以直接访问,即使不登录也可以访问。一般将login页面放给这个权限。and()。formLogin()。loginProcessingUrl(loginuser)用来定义什么样的API请求时login请求。permitAll()login请求需要是所有权限都可以的。and()。csrf()。disable();将自定义的JWT过滤器加入configure中JWTAuthenticationFilterjwtAuthenticationFilternewJWTAuthenticationFilter(this。authenticationManager());http。addFilterBefore(jwtAuthenticationFilter,JWTAuthenticationFilter。class);}AutowiredprivateMyUserDetailsServicemyUserDetailsService;认证Overrideprotectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{auth。userDetailsService(myUserDetailsService);}}
  MyUserDetailsServiceServicepublicclassMyUserDetailsServiceimplementsUserDetailsService{ResourceprivateUsersRepositoryusersRepository;其实这样就完成了认证的过程,能获取到数据库中配置的用户信息paramusernamereturnthrowsUsernameNotFoundExceptionOverridepublicUserDetailsloadUserByUsername(Stringusername)throwsUsernameNotFoundException{获取该用户的信息UsersuserusersRepository。findByUsername(username);if(usernull){用户不存在报错thrownewUsernameNotFoundException(用户不存在);}将roles信息转换成SpringSecurity内部的形式,即AuthoritiescommaSeparatedStringToAuthorityList可以将使用,隔开的角色列表切割出来并赋值List如果不行的话,也可以自己实现这个方法,只要拆分出来就可以了注意,这里放入Authorities中的信息,都需要是以Role开头的,所以我们在数据库中配置的都是这种格式的。当我们使用hasRole做比对的时候,必须要是带Role开头的。否则可以使用hasAuthority方法做比对user。setAuthorities(AuthorityUtils。commaSeparatedStringToAuthorityList(user。getRoles()));returnuser;}}
  其实如果去掉上面的将自定义的JWT过滤器加入到过滤链中的话,这个认证过程已经完成了。使用下面的代码就可以调用起整个认证程序。
  核心代码authenticateauthenticationManager。authenticate(newUsernamePasswordAuthenticationToken(userDto。getUsername(),userDto。getPassword()));
  这一行就会将username和password放到认证程序中进行认证。
  也就是需要我们自己的逻辑让他去触发这个代码的实现。就可以自动完成认证程序了。就会触发使用username获取到数据库用户信息,然后经过密码加密比对之后会将认证结果返回。
  我们整合JWT其实也很简单,其实就是将JWT的登录部分的操作,使用过滤器封装,将该过滤器放到整个认证的过滤链中2。自定义JWT过滤器的配置
  SpringSecurity过滤器的配置无非以下几个条件该过滤器过滤什么样的API请求(也就是说什么样的API请求会触发该过滤器执行)。配置被过滤的请求API该过滤器做什么事该过滤器执行成功以及执行失败的各种情况该怎么做该过滤器执行的时机是什么样的,也就是在过滤链之前还是之后执行
  先解决逻辑上以上三个问题的答案我们需要拦截认证请求,肯定是形如xxxloginxxx这种API接口的请求啦这个过滤器会做什么事呢?首先,我们需要进行用户名密码的基础验证,也就是合不合法我们需要调用起SpringSecurity的默认认证程序认证程序执行成功之后,我们需要按照用户的信息以JWT的规则生成一个JWTToken并将其放入response中返回回去认证程序执行失败,也就是用户登录失败,我们也需要将返回信息封装起来返回给用户执行成功,我们需要返回给用户JWTToken信息。执行失败,我们也要友好提示用户如果排除其他的业务场景干扰,目前过滤链只有进行鉴权时候才使用。所以针对不同的业务场景,这个过滤器放的地方其实是不一样的。(之后我们的另一个JWTToken校验的过滤器应该需要在这个认证的过滤器之后(两个其实并不捕捉同样的APi所以不会依次执行。也不用太考虑这个问题))(我记得SpringCloud中的zuul网关的过滤器是可以自定义级别的。但是目前在SpringSecurity中尚未发现这种功能)
  针对以上解答,下面用代码来做展示(ps:序号依次对应上面)配置过滤器过滤地址下面是为了配置这个Manager配置其拦截的API请求地址paramauthenticationManagerpublicJWTAuthenticationFilter(AuthenticationManagerauthenticationManager){this。authenticationManagerauthenticationManager;super。setFilterProcessesUrl(loginuser);这里指定什么样的API请求会被这个过滤器拦截}配置过滤器职能OverridepublicAuthenticationattemptAuthentication(HttpServletRequestrequest,HttpServletResponseresponse)throwsAuthenticationException{这里是定义一个拦截器,在认证方面的拦截器,当请求的时候回拦截到这里面然后进行身份认证验证用户名密码是否正确之后Authenticationauthenticatenull;try{System。out。println(InputStream:request。getInputStream());UserDtouserDtonewObjectMapper()。readValue(request。getInputStream(),UserDto。class);这个地方相当于封装一下请求,因为前台请求的是user。usernamexxx这种对象的形式。对于这个过滤器拦截的接口,去调用SpringSecurity默认的认证程序,也就是去进行SpringSecurity的认证authenticateauthenticationManager。authenticate(newUsernamePasswordAuthenticationToken(userDto。getUsername(),userDto。getPassword()));returnauthenticate;如果返回成功,就进入successfulAuthentication。返回失败就进入unsuccessfulAuthentication可以通过下面的定义来让前端得到不同的返回从而向用户展示不同的效果TODO这个地方还有点问题,如果密码错误了,就会报BadCredentialsException错误。需要看一下如果不让这么报错并让他进入到unsuccessfulAuthentication方法中}catch(BadCredentialsExceptione){捕捉密码验证错误异常log。info(密码错误);try{this。unsuccessfulAuthentication(request,response,e);}catch(IOExceptionex){ex。printStackTrace();}catch(ServletExceptionex){ex。printStackTrace();}}catch(Exceptione){e。printStackTrace();}returnnull;}OverrideprotectedvoidsuccessfulAuthentication(HttpServletRequestrequest,HttpServletResponseresponse,FilterChainchain,AuthenticationauthResult)throwsIOException,ServletException{当身份验证通过之后,会进入这里,这里可以定义成功的返回Usersuser(Users)authResult。getPrincipal();将principal中的信息转换成User对象JwtUtilutilnewJwtUtil(secretKey,SignatureAlgorithm。HS256);MapString,ObjectmapnewHashMap();map。put(username,user。getUsername());map。put(password,user。getPassword());StringjwtTokenutil。encode(tom,30000,map);response。addHeader(Authorizations,jwtToken);user。setJwtToken(jwtToken);ResponseUtil。write(response,JSONObject。toJSONString(ResultUtil。success(user)));System。out。println(response。getHeaderNames());super。successfulAuthentication(request,response,chain,authResult);注意,不要使用默认的super来定义,否则上述会失效的}OverrideprotectedvoidunsuccessfulAuthentication(HttpServletRequestrequest,HttpServletResponseresponse,AuthenticationExceptionfailed)throwsIOException,ServletException{TODO得看一下为啥会报这个错误System。out。println(认证失败);ResponseUtil。write(response,JSONObject。toJSONString(ResultUtil。error(登录失败,账号密码错误)));}执行失败与成功,分别是2中的unsuccessfulAuthentication和successfulAuthentication方法配置过滤链执行的位置在WebSecurityConfig中的configure(HttpSecurityhttp)方法中JWTAuthenticationFilterjwtAuthenticationFilternewJWTAuthenticationFilter(this。authenticationManager());http。addFilterBefore(jwtAuthenticationFilter,JWTAuthenticationFilter。class);复制代码
  完成了以上的配置,前台就可以使用loginuser来进行登录操作了。登录成功会返回一个JSON对象来供前端判断成功与否2。代码结果
  全部代码奉上,随意写的注释有点多,不看的可以给删掉WebSecurityConfigimportorg。springframework。beans。factory。annotation。Autowired;importorg。springframework。context。annotation。Bean;importorg。springframework。security。authentication。AuthenticationManager;importorg。springframework。security。config。annotation。authentication。builders。AuthenticationManagerBuilder;importorg。springframework。security。config。annotation。web。builders。HttpSecurity;importorg。springframework。security。config。annotation。web。configuration。EnableWebSecurity;importorg。springframework。security。config。annotation。web。configuration。WebSecurityConfigurerAdapter;importorg。springframework。security。crypto。bcrypt。BCryptPasswordEncoder;importorg。springframework。security。crypto。password。NoOpPasswordEncoder;importorg。springframework。security。crypto。password。PasswordEncoder;description:author:coderymycreate:2020100113:54p1。创建WebSecurityConfig类继承WebSecurityConfigurerAdapter2。类上加上EnableWebSecurity,注解中包括Configuration注解pWebSecurityConfigurerAdapter声明了一些默认的安全特性(1)验证所有的请求(2)可以使用springSecurity默认的表单页面进行验证登录(3)允许用户使用http请求进行验证如何自定义认证1。实现并重写configure(HttpSecurityhttp)方法,鉴权,也就是判断该用户是否有访问该api的权限pp页面显示403错误,表示该用户授权失败(401代表该用户认证失败)前端可以使用返回的状态码来标识如何给用户展示用2XX表示本次操作成功,用4XX表示是客户端导致的失败,用5XX表示是服务器引起的错误EnableWebSecuritypublicclassWebSecurityConfigextendsWebSecurityConfigurerAdapter{publicstaticvoidmain(String〔〕args){BCryptPasswordEncoderpasswordEncodernewBCryptPasswordEncoder();StringencodepasswordEncoder。encode(123);System。out。println(encode);}BeanOverridepublicAuthenticationManagerauthenticationManagerBean()throwsException{AuthenticationManagermanagersuper。authenticationManagerBean();returnmanager;}SpringSecurity5。X要求必须指定密码加密方式,否则会在请求认证的时候报错同样的,如果指定了加密方式,就必须您的密码在数据库中存储的是加密后的,才能比对成功returnBeanpublicBCryptPasswordEncoderpasswordEncoder(){returnnewBCryptPasswordEncoder();}鉴权Overrideprotectedvoidconfigure(HttpSecurityhttp)throwsException{1。HttpSecurity被声明为链式调用其中配置方法包括1。authorizeRequests()url拦截配置2。formLogin()表单验证3。httpBasic()表单验证4。csrf()提供的跨站请求伪造防护功能2。authorizeRequests目的是指定url进行拦截的,也就是默认这个url是也就是所有的anyanyRequest()、antMatchers()和regexMatchers()三种方法来拼配系统的url。并指定安全策略http。authorizeRequests()这里指定什么样的接口地址的请求,需要什么样的权限ANT模式的URL匹配器。antMatchers(select)。hasRole(USER)用户可以有查询权限。antMatchers(insert)。hasRole(ADMIN)管理员可以有插入权限权限。antMatchers(empower)。hasRole(SUPERADMIN)超级管理员才有赋权的权限。antMatchers(login)。permitAll()标识list所有权限都可以直接访问,即使不登录也可以访问。一般将login页面放给这个权限。and()。formLogin()。loginProcessingUrl(loginuser)用来定义什么样的API请求时login请求。permitAll()login请求需要是所有权限都可以的。and()。csrf()。disable();将自定义过滤器加入configure中JWTAuthenticationFilterjwtAuthenticationFilternewJWTAuthenticationFilter(this。authenticationManager());http。addFilterBefore(jwtAuthenticationFilter,JWTAuthenticationFilter。class);}AutowiredprivateMyUserDetailsServicemyUserDetailsService;认证Overrideprotectedvoidconfigure(AuthenticationManagerBuilderauth)throwsException{auth。userDetailsService(myUserDetailsService);}}JWTAuthenticationFilterimportcom。alibaba。fastjson。JSONObject;importcom。fasterxml。jackson。databind。ObjectMapper;importcom。huanong。avatarma。basic。entity。Users;importcom。huanong。avatarma。basic。model。vo。UserDto;importcom。huanong。avatarma。common。util。JwtUtil;importcom。huanong。avatarma。common。util。ResponseUtil;importcom。huanong。avatarma。common。util。ResultUtil;importio。jsonwebtoken。SignatureAlgorithm;importlombok。extern。slf4j。Slf4j;importorg。springframework。context。annotation。Configuration;importorg。springframework。security。authentication。AuthenticationManager;importorg。springframework。security。authentication。BadCredentialsException;importorg。springframework。security。authentication。UsernamePasswordAuthenticationToken;importorg。springframework。security。core。Authentication;importorg。springframework。security。core。AuthenticationException;importorg。springframework。security。web。authentication。UsernamePasswordAuthenticationFilter;importorg。springframework。stereotype。Component;importjavax。servlet。FilterChain;importjavax。servlet。ServletException;importjavax。servlet。http。HttpServletRequest;importjavax。servlet。http。HttpServletResponse;importjava。io。IOException;importjava。util。HashMap;importjava。util。Map;description:jwt拦截器这个定义完成之后,想要生效还需要将其加入到过滤链中author:coderymycreate:2020100209:36Slf4jpublicclassJWTAuthenticationFilterextendsUsernamePasswordAuthenticationFilter{验证用户名密码是否正确之后,生成一个token,并将token返回客户端paramrequestparamresponsereturnthrowsAuthenticationExceptionprivateStringsecretKeyILoveDanChaoFan;privateAuthenticationManagerauthenticationManager;下面是为了配置这个Manager配置其拦截的API请求地址paramauthenticationManagerpublicJWTAuthenticationFilter(AuthenticationManagerauthenticationManager){this。authenticationManagerauthenticationManager;super。setFilterProcessesUrl(loginuser);这里指定什么样的API请求会被这个过滤器拦截}OverridepublicAuthenticationattemptAuthentication(HttpServletRequestrequest,HttpServletResponseresponse)throwsAuthenticationException{这里是定义一个拦截器,在认证方面的拦截器,当请求的时候回拦截到这里面然后进行身份认证验证用户名密码是否正确之后Authenticationauthenticatenull;try{System。out。println(InputStream:request。getInputStream());UserDtouserDtonewObjectMapper()。readValue(request。getInputStream(),UserDto。class);这个地方相当于封装一下请求,因为前台请求的是user。usernamexxx这种对象的形式。对于这个过滤器拦截的接口,去调用SpringSecurity默认的认证程序,也就是去进行SpringSecurity的认证authenticateauthenticationManager。authenticate(newUsernamePasswordAuthenticationToken(userDto。getUsername(),userDto。getPassword()));returnauthenticate;如果返回成功,就进入successfulAuthentication。返回失败就进入unsuccessfulAuthentication可以通过下面的定义来让前端得到不同的返回从而向用户展示不同的效果TODO这个地方还有点问题,如果密码错误了,就会报BadCredentialsException错误。需要看一下如果不让这么报错并让他进入到unsuccessfulAuthentication方法中}catch(BadCredentialsExceptione){捕捉密码验证错误异常log。info(密码错误);try{this。unsuccessfulAuthentication(request,response,e);}catch(IOExceptionex){ex。printStackTrace();}catch(ServletExceptionex){ex。printStackTrace();}}catch(Exceptione){e。printStackTrace();}returnnull;}OverrideprotectedvoidsuccessfulAuthentication(HttpServletRequestrequest,HttpServletResponseresponse,FilterChainchain,AuthenticationauthResult)throwsIOException,ServletException{当身份验证通过之后,会进入这里,这里可以定义成功的返回Usersuser(Users)authResult。getPrincipal();将principal中的信息转换成User对象JwtUtilutilnewJwtUtil(secretKey,SignatureAlgorithm。HS256);MapString,ObjectmapnewHashMap();map。put(username,user。getUsername());map。put(password,user。getPassword());StringjwtTokenutil。encode(tom,30000,map);response。addHeader(Authorizations,jwtToken);user。setJwtToken(jwtToken);ResponseUtil。write(response,JSONObject。toJSONString(ResultUtil。success(user)));System。out。println(response。getHeaderNames());super。successfulAuthentication(request,response,chain,authResult);注意,不要使用默认的super来定义,否则上述会失效的}OverrideprotectedvoidunsuccessfulAuthentication(HttpServletRequestrequest,HttpServletResponseresponse,AuthenticationExceptionfailed)throwsIOException,ServletException{TODO得看一下为啥会报这个错误System。out。println(认证失败);ResponseUtil。write(response,JSONObject。toJSONString(ResultUtil。error(登录失败,账号密码错误)));}}MyUserDetailsServiceimportcom。huanong。avatarma。basic。dao。UsersRepository;importcom。huanong。avatarma。basic。entity。Users;importorg。springframework。security。core。authority。AuthorityUtils;importorg。springframework。security。core。userdetails。UserDetails;importorg。springframework。security。core。userdetails。UserDetailsService;importorg。springframework。security。core。userdetails。UsernameNotFoundException;importorg。springframework。stereotype。Service;importjavax。annotation。Resource;description:author:coderymycreate:2020100115:55ServicepublicclassMyUserDetailsServiceimplementsUserDetailsService{ResourceprivateUsersRepositoryusersRepository;其实这样就完成了认证的过程,能获取到数据库中配置的用户信息paramusernamereturnthrowsUsernameNotFoundExceptionOverridepublicUserDetailsloadUserByUsername(Stringusername)throwsUsernameNotFoundException{获取该用户的信息UsersuserusersRepository。findByUsername(username);if(usernull){用户不存在报错thrownewUsernameNotFoundException(用户不存在);}将roles信息转换成SpringSecurity内部的形式,即AuthoritiescommaSeparatedStringToAuthorityList可以将使用,隔开的角色列表切割出来并赋值List如果不行的话,也可以自己实现这个方法,只要拆分出来就可以了注意,这里放入Authorities中的信息,都需要是以Role开头的,所以我们在数据库中配置的都是这种格式的。当我们使用hasRole做比对的时候,必须要是带Role开头的。否则可以使用hasAuthority方法做比对user。setAuthorities(AuthorityUtils。commaSeparatedStringToAuthorityList(user。getRoles()));returnuser;}}UsersDataToStringEntityTable(nameusers)publicclassUsersimplementsUserDetails{IdGeneratedValue(strategyGenerationType。IDENTITY)privateLongid;privateStringusername;privateStringpassword;privatebooleanenable;privateStringroles;privateDatecreateDate;privateDatemodifyDate;Transient这个注解可以帮助在entity中添加表中没有的字段privateListGrantedAuthorityauthorities;TransientprivateStringjwtToken;OverridepublicCollectionlt;?extendsGrantedAuthoritygetAuthorities(){这个本身是对应roles字段的,但是因为结构不一致,所以重新创建一个,后续补充这部分returnthis。authorities;}OverridepublicbooleanisAccountNonExpired(){returntrue;}OverridepublicbooleanisAccountNonLocked(){returntrue;}OverridepublicbooleanisCredentialsNonExpired(){returntrue;}publicvoidsetAuthorities(ListGrantedAuthorityauthorities){this。authoritiesauthorities;}OverridepublicbooleanisEnabled(){returnthis。enable;}}Resultimportlombok。Data;importlombok。ToString;description:author:coderymycreate:2020100213:24DataToStringpublicclassResult{privateIntegercode;privateStringmsg;privateObjectdata;}复制代码JwtUtildescription:author:coderymycreate:2020100209:24importcom。auth0。jwt。JWT;importcom。auth0。jwt。JWTVerifier;importcom。auth0。jwt。algorithms。Algorithm;importio。jsonwebtoken。Claims;importio。jsonwebtoken。JwtBuilder;importio。jsonwebtoken。Jwts;importio。jsonwebtoken。SignatureAlgorithm;importorg。apache。commons。codec。binary。Base64;importjava。util。Date;importjava。util。HashMap;importjava。util。Map;importjava。util。UUID;importjava。util。;总的来说,工具类中有三个方法获取JwtToken,获取JwtToken中封装的信息,判断JwtToken是否存在1。encode(),参数是签发人,存在时间,一些其他的信息。返回值是JwtToken对应的字符串2。decode(),参数是JwtToken。返回值是荷载部分的键值对3。isVerify(),参数是JwtToken。返回值是这个JwtToken是否存在publicclassJwtUtil{创建默认的秘钥和算法,供无参的构造方法使用privatestaticfinalStringdefaultbase64EncodedSecretKeybadbabe;privatestaticfinalSignatureAlgorithmdefaultsignatureAlgorithmSignatureAlgorithm。HS256;publicJwtUtil(){this(defaultbase64EncodedSecretKey,defaultsignatureAlgorithm);}privatefinalStringbase64EncodedSecretKey;privatefinalSignatureAlgorithmsignatureAlgorithm;publicJwtUtil(StringsecretKey,SignatureAlgorithmsignatureAlgorithm){this。base64EncodedSecretKeyBase64。encodeBase64String(secretKey。getBytes());this。signatureAlgorithmsignatureAlgorithm;}这里就是产生jwt字符串的地方jwt字符串包括三个部分1。header当前字符串的类型,一般都是JWT哪种算法加密,HS256或者其他的加密算法所以一般都是固定的,没有什么变化2。payload一般有四个最常见的标准字段(下面有)iat:签发时间,也就是这个jwt什么时候生成的jti:JWT的唯一标识iss:签发人,一般都是username或者userIdexp:过期时间publicStringencode(Stringiss,longttlMillis,MapString,Objectclaims){iss签发人,ttlMillis生存时间,claims是指还想要在jwt中存储的一些非隐私信息if(claimsnull){claimsnewHashMap();}longnowMillisSystem。currentTimeMillis();JwtBuilderbuilderJwts。builder()。setClaims(claims)。setId(UUID。randomUUID()。toString())2。这个是JWT的唯一标识,一般设置成唯一的,这个方法可以生成唯一标识。setIssuedAt(newDate(nowMillis))1。这个地方就是以毫秒为单位,换算当前系统时间生成的iat。setSubject(iss)3。签发人,也就是JWT是给谁的(逻辑上一般都是username或者userId)。signWith(signatureAlgorithm,base64EncodedSecretKey);这个地方是生成jwt使用的算法和秘钥if(ttlMillis0){longexpMillisnowMillisttlMillis;DateexpnewDate(expMillis);4。过期时间,这个也是使用毫秒生成的,使用当前时间前面传入的持续时间生成builder。setExpiration(exp);}returnbuilder。compact();}相当于encode的方向,传入jwtToken生成对应的username和password等字段。Claim就是一个map也就是拿到荷载部分所有的键值对publicClaimsdecode(StringjwtToken){得到DefaultJwtParserreturnJwts。parser()设置签名的秘钥。setSigningKey(base64EncodedSecretKey)设置需要解析的jwt。parseClaimsJws(jwtToken)。getBody();}判断jwtToken是否合法publicbooleanisVerify(StringjwtToken){这个是官方的校验规则,这里只写了一个校验算法,可以自己加Algorithmalgorithmnull;switch(signatureAlgorithm){caseHS256:algorithmAlgorithm。HMAC256(Base64。decodeBase64(base64EncodedSecretKey));break;default:thrownewRuntimeException(不支持该算法);}JWTVerifierverifierJWT。require(algorithm)。build();verifier。verify(jwtToken);校验不通过会抛出异常判断合法的标准:1。头部和荷载部分没有篡改过。2。没有过期returntrue;}publicstaticvoidmain(String〔〕args){JwtUtilutilnewJwtUtil(tom,SignatureAlgorithm。HS256);以tom作为秘钥,以HS256加密MapString,ObjectmapnewHashMap();map。put(username,tom);map。put(password,123456);map。put(age,20);StringjwtTokenutil。encode(tom,30000,map);System。out。println(jwtToken);util。decode(jwtToken)。entrySet()。forEach((entry){System。out。println(entry。getKey():entry。getValue());});}}ResponseUtil、ResultUtil、repository等不做展示。需要的可以联系我,这个是基础性的东西依赖dependencygroupIdorg。springframework。bootgroupIdspringbootstarterdatajpaartifactIddependencydependencygroupIdorg。springframework。bootgroupIdspringbootstarterwebartifactIddependencydependencygroupIdmysqlgroupIdmysqlconnectorjavaartifactIdscoperuntimescopedependencydependencygroupIdorg。projectlombokgroupIdlombokartifactIdoptionaltrueoptionaldependencydependencygroupIdorg。springframework。bootgroupIdspringbootstartersecurityartifactIddependencydependencygroupIdcom。auth0groupIdjavajwtartifactIdversion3。11。0versiondependencydependencygroupIdio。jsonwebtokengroupIdjjwtartifactIdversion0。9。1versiondependencydependencygroupIdorg。springframework。securitygroupIdspringsecurityjwtartifactIdversion1。0。10。RELEASEversiondependency

越南电子商务前景广阔,但面临这个痛点海外商业观察在细分行业中,电子、时尚、玩具和家具是越南电子商务行业中增长最快的子行业。电子产品的增速和规模位居首位,20172020年间每年以近27的速度增长,预计到2025年规模将达到2……我们的智慧校园四年级作文500字校园,是每个人必须经历的一种考验,每个人都需要克服各种各样的关卡,每过一关就会得到相应的知识果实,到达知识的顶峰。正在经历小学考验的我,才得到八颗知识果实,下面,我带你们……北大博士卧底,揭开中国巨头黑幕内幕惊人在5个月的送外卖过程中,北大博士陈龙渐渐发现自己快到停不下来了。他意外体验到了一种上瘾的感觉,或许也就此成为外卖平台数字控制下的一个新俘虏。2018年,正在筹备博士论文选……2018年初一年级家长期末评语大全希望我女儿虚心的学习,有特长之处加强学,不断上进,不足之处要加强学习,力争具有高尚的道德情操,良好的文化素养。小编与读者分享初一年级家长期末评语,欢迎大家参考借鉴。初一年级家长……亚马逊全球开店发布最新调研中国卖家更加重视品牌塑造来源:经济日报亚马逊全球开店发布的最新数据显示,随着出口跨境电商行业的快速发展,企业品牌价值愈发凸显,中国卖家更加重视品牌塑造。越来越多的中国卖家通过亚马逊加速了品牌国际……学会倾听在生活中,我们往往有听到很多声音,但是声音并不是都那么好听,也有不少的噪音,但是你如果仔细地去倾听,你就会发现,世间的万物都很好听。轰轰的,一声响雷,把我从睡梦惊醒,真是……我的学习生活学生作文人常说:活到老,学到老。这足以说明学习应该贯穿人一生。可以说我是一个热爱学习的人,从来不以学习为苦,因为学习使我增长知识、开阔眼界。学生时代就是以学习为主要任务,而我也总……游绣山公园小学作文500字二月二十一日,我和妈妈一起游玩了美丽的绣山公园。那天早上,我和妈妈乘八路车去绣山公园玩。我们在车上边说边笑。嘿!你们看,绿化带上一堆堆的,大大的,绿油油的蘑菇。还有的蘑菇……精选小学桂花作文500字4篇在平平淡淡的日常中,许多人都写过作文吧,写作文可以锻炼我们的独处习惯,让自己的心静下来,思考自己未来的方向。那么问题来了,到底应如何写一篇优秀的作文呢?以下是小编为大家整理的小……珍藏我的泪与笑作文微风把春天的门推开了;绿草把夏天的门推开了;红叶把秋天的门推开了;飞雪把冬天的门推开了;五颜六色的干花瓣把我的记忆之门推开了。独自在家时我常常拿出一袋干花,花儿不多,只有……雷蛇发布新款ZephyrPro面罩新增语音放大功能近日,雷蛇在CES2022展上发布了新款RazerZephyrPro面罩,此新品依然沿用该系列一贯的科幻RGB风格,在旧款的基础上新增了语音放大功能,便于佩戴者佩戴此款Raze……无泪天使作文有一种人,从一出生就漂泊在路上的人,像一叶浮萍,被隔离在天与水之间,而水和天都不是她的家。。。。。。一个孩子,如果她应该快乐的时间没有快乐;在渴望赞赏的时期听到的都是否定,在应……
妈妈我人生中有许多人疼爱我,我的朋友,我的姐姐,我的妹妹,我的爸爸hellip;hellip;有一种爱让我刻骨难忘,那就是mdash;mdash;母爱。母爱如水。有时候,爸爸……描写感恩父母作文800字作文一:感恩父母当我们蹒跚学步时,是谁在一旁耐心地扶着我们,不让我们摔倒?当我们牙牙学语时,是谁温柔地教学,吐字清晰地告诉我们怎么读?当我们感到悲伤时,是谁安慰我们,在雪……爱需要表达高考作文父母的爱多姿多味,甜的,苦的,酸的辣的,多姿多味,只要我们要去感受。小编收集了爱需要表达作文,欢迎阅读。第一篇:爱需要表达一直以来,我理所应当地享受着父母带给我的一切,从……争做一个文明的小学生争做一个文明的小学生老师们同学们大家好,我是来自高场镇小学五年级一班的邱浩思同学。今天我为大家演讲的题目是《争做一个文明的小学生》。要争做一个文明的小学生。讲究卫生,维护……青春的约定小学作文我坐在桌前痴痴地发呆,桌上摆放着许多照片。我心中一直想着昨天接到的那个电话:喂,请问是莹莹家吗?当我听到这个既有些熟悉又似乎有些陌生的声音时,我愕然了。是她,娟。我……公告精选小米授出超5500万股奖励股份招商银行董事会批准全额重磅公告精选1、小米集团W(01810。HK):授出合共5534。8201万股奖励股份小米集团W(01810)宣布,董事会于2022年5月20日根据股份奖励计划奖励……未来的衣服小学作文篇一:人们都知道1236。那么谁知道外衣雨衣吸尘器等于什么?你们一定有知道吧,它等于超级外衣。超级外衣有什么功能呢?大家请看衣角,那里有三个十分精细的按钮,第一个按……叫老爸起床三部曲五年级作文每当周末的时候,老爸和我又会上演《睡美人》的戏剧。他就是那个贪睡的睡美人,我就是那个负责叫醒他的王子。不过,我老爸可不是一个吻就能唤醒的,为此我还准备了三样绝密武器。今天,我就……对父亲感激之情的作文导语:总是埋怨父亲做得不够,可现在,作为父亲的女儿,我不由地愧疚,不由地感激下面是小编给大家整理的对父亲感激之情的作文内容,希望能给你带来帮助!对父亲感激之情的作文1我的……安全生产警言警句安全第一,警钟常鸣。安全第一,人人牢记。安全生产,齐抓共管。生产大上,安全不忘。千里之堤,溃于蚁穴。一人安全,全家幸福。一人违章,众人遭殃。疏忽一时,痛苦一世。大事……描写运动会的优美段落(校运会通讯稿)更多关于运动会的作文阳光总在风雨后mdash;mdash;致运动场上暂时的失败者真的,人生要是能有一个草稿,能再誊写一次,那该多好!我们会绝对认真地叙写自己的人生,……必备五一劳动节的作文400字汇编九篇在我们平凡的日常里,大家或多或少都会接触过作文吧,作文根据写作时限的不同可以分为限时作文和非限时作文。作文的注意事项有许多,你确定会写吗?下面是小编收集整理的五一劳动节的作文4……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网