当前位置: 首页 > news >正文

天津南开做网站公司上海发布微信公众号

天津南开做网站公司,上海发布微信公众号,wordpress怎么安装访问不了,无锡高端网站建设咨询系统的登录,都做些什么?用户访问登录页时:会发起一个获取图片验证码的请求,后端先生成一个uuid代表此次的验证码,接着生成 "ab?答案" 的表达式,将前面的内容转换成流生成图片,后面的答案则存储到…

系统的登录,都做些什么?

用户访问登录页时:

会发起一个获取图片验证码的请求,后端先生成一个uuid代表此次的验证码,接着生成 "a+b=?@答案" 的表达式,将@前面的内容转换成流生成图片,@后面的答案则存储到redis中,设为2分钟过期,将图片和uuid传给前端。

/*** 生成验证码*/@GetMapping("**/captchaImage")public AjaxResult getCode(HttpServletResponse response) throws IOException{AjaxResult ajax = AjaxResult.success();boolean captchaOnOff = configService.selectCaptchaOnOff();ajax.put("captchaOnOff", captchaOnOff);if (!captchaOnOff){return ajax;}// 保存验证码信息String uuid = IdUtils.simpleUUID();String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;String capStr = null, code = null;BufferedImage image = null;// 生成验证码String captchaType = RuoYiConfig.getCaptchaType();if ("math".equals(captchaType)){String capText = captchaProducerMath.createText();capStr = capText.substring(0, capText.lastIndexOf("@"));code = capText.substring(capText.lastIndexOf("@") + 1);image = captchaProducerMath.createImage(capStr);}else if ("char".equals(captchaType)){capStr = code = captchaProducer.createText();image = captchaProducer.createImage(capStr);}redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);// 转换流信息写出FastByteArrayOutputStream os = new FastByteArrayOutputStream();try{ImageIO.write(image, "jpg", os);}catch (IOException e){return AjaxResult.error(e.getMessage());}ajax.put("uuid", uuid);ajax.put("img", Base64.encode(os.toByteArray()));return ajax;}

发起登录请求:

后端会先根据图片uuid从redis中取出验证码进行校验,校验通过则执行下面代码,SpringSecurity框架就会对账号密码进行一系列的过滤器进行验证和授权等,其中最重要的两个过滤器就是UsernamePasswordAuthenticationFilter负责登录认证,FilterSecurityInterceptor负责权限授权。

// 用户验证,当前登录用户的认证信息
Authentication authentication = null;// 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
authentication = authenticationManager.
authenticate(new UsernamePasswordAuthenticationToken(username, password));

Spring Security大致源码:

@Override
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {...省略其他代码// 获取Spring Security的一套过滤器List<Filter> filters = getFilters(request);// 将这一套过滤器组成Spring Security自己的过滤链,并开始执行VirtualFilterChain vfc = new VirtualFilterChain(fwRequest, chain, filters);vfc.doFilter(request, response);...省略其他代码
}

Spring Security的核心逻辑全在这一套过滤器中,过滤器里会调用各种组件完成功能,掌握了这些过滤器和组件你就掌握了Spring Security,当然我还没全部掌握,还要继续学习!

这里面我们只需要重点关注两个过滤器即可:UsernamePasswordAuthenticationFilter负责登录认证,FilterSecurityInterceptor负责权限授权。

SpringSecurity配置类

@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
{/*** 自定义用户认证逻辑*/@Autowiredprivate UserDetailsService userDetailsService;/*** 认证失败处理类*/@Autowiredprivate AuthenticationEntryPointImpl unauthorizedHandler;/*** 退出处理类*/@Autowiredprivate LogoutSuccessHandlerImpl logoutSuccessHandler;/*** token认证过滤器*/@Autowiredprivate JwtAuthenticationTokenFilter authenticationTokenFilter;/*** 跨域过滤器*/@Autowiredprivate CorsFilter corsFilter;/*** 解决 无法直接注入 AuthenticationManager** @return* @throws Exception*/@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception{return super.authenticationManagerBean();}/*** anyRequest          |   匹配所有请求路径* access              |   SpringEl表达式结果为true时可以访问* anonymous           |   匿名可以访问* denyAll             |   用户不能访问* fullyAuthenticated  |   用户完全认证可以访问(非remember-me下自动登录)* hasAnyAuthority     |   如果有参数,参数表示权限,则其中任何一个权限可以访问* hasAnyRole          |   如果有参数,参数表示角色,则其中任何一个角色可以访问* hasAuthority        |   如果有参数,参数表示权限,则其权限可以访问* hasIpAddress        |   如果有参数,参数表示IP地址,如果用户IP和参数匹配,则可以访问* hasRole             |   如果有参数,参数表示角色,则其角色可以访问* permitAll           |   用户可以任意访问* rememberMe          |   允许通过remember-me登录的用户访问* authenticated       |   用户登录后可访问*/@Overrideprotected void configure(HttpSecurity httpSecurity) throws Exception{httpSecurity// CSRF禁用,因为不使用session.csrf().disable()// 认证失败处理类.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()// 基于token,所以不需要session.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()// 过滤请求.authorizeRequests()// 对于登录login 注册register 验证码captchaImage 允许匿名访问.antMatchers("/login", "/api/pwd/login", "/api/phone/*", "/api/email/login", "/register", "/**/captchaImage","/info/member/selectMemByName","/sys/message/getMessageCode", "/info/member","/back/oss/upload").anonymous().antMatchers(HttpMethod.GET,"/","/*.html","/**/*.html","/**/*.css","/**/*.js","/profile/**","/controller/appMenu/list").permitAll().antMatchers("/swagger-ui.html").anonymous().antMatchers("/swagger-resources/**").anonymous().antMatchers("/webjars/**").anonymous().antMatchers("/*/api-docs").anonymous().antMatchers("/druid/**").anonymous()// 除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated().and().headers().frameOptions().disable();httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);// 添加JWT filterhttpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);// 添加CORS filterhttpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);}/*** 强散列哈希加密实现*/@Beanpublic BCryptPasswordEncoder bCryptPasswordEncoder(){return new BCryptPasswordEncoder();}/*** 身份认证接口*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception{auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());}
}

JWT生成token

先生成一个uuid代表当前登录对象(含用户的权限信息),然后将此登录对象存到redis中,key是uuid,接着JWT根据这个uuid以及签名密钥加密生成token

    public String createToken(LoginUser loginUser){String token = IdUtils.fastUUID();loginUser.setToken(token);setUserAgent(loginUser);refreshToken(loginUser);Map<String, Object> claims = new HashMap<>();claims.put(Constants.LOGIN_USER_KEY, token);return createToken(claims);}

JWT生成的token

以下加密的token:

eyJhbGciOiJIUzUxMiJ9.
eyJsb2dpbl91c2VyX2tleSI6IjU0ZWQwOWJmLTA4OTgtNDI5OC1hYTYzLTEyNmQ2MTNiNDk5ZSJ9.
wNI9cYMOpfSDhcECVHpF3yxVLQbefs7vJl2lRaGlBmDckIvV1U2_PrS1CyQoE53sGgDzZEXfbyeHSmqhGH0NQ

它是一个很长的字符串,中间用点(.)分隔成三个部分。

JWT生成的token包括以下三个部分:
Header(头部)
Payload(负载)
Signature(签名)
Header.Payload.Signature

Header(头部)

Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常是下面的样子。

{"alg":"HS256","typ":"JWT"}

alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT。

Payload(负载)

Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。

iss (issuer):签发人
exp (expiration time):过期时间
sub (subject):主题
aud (audience):受众
nbf (Not Before):生效时间
iat (Issued At):签发时间
jti (JWT ID):编号

除了官方字段,还可以在这个部分自定义字段,可以将代表当前用户的uuid设置进去

{
login_user_key=2e80aa6d-d849-444d-9cbf-0f5a86d48db4
},

Signature(签名)

Signature 部分是对前两部分的签名,防止数据篡改,防止别人仿造token。

首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

前端保存token

客户端收到服务器返回的经JWT加密后的token后,可以储存在 Cookie 里面,也可以储存在 localStorage。

此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域(可以在前端配置代理服务器解决),所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。

此后每次发请求,做些什么?

1、登录验证

用户发送请求时会经过一个前端的一个请求拦截器判断是否需要携带token,默认所有的请求都是携带token的,除了一些登录、注册的请求需要手动设置不带token。发送请求后,后端设置了一个token验证过滤器,先取出请求头中的token,然后解析这个由jwt加密后的token,接着取出token中的负载信息(也就是代表当前登录用户的uuid)。接着取出redis中登录的用户对象(含权限信息),先验证token有效期,若低于20分钟则刷新redis中的用户对象有效期(防止产生频繁登录,影响体验),最后将取出的用户对象放入SpringSecurity的安全上下文中,通过登录验证后,则执行用户原本请求的接口。若没通过验证则执行自定义的未授权处理类,返回未授权提示。

/*** token过滤器 验证token有效性** 会拦截所有的请求,进行登录认证,认证成功则放行,否则执行AuthenticationEntryPointImpl类中的方法** @author ruoyi*/
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
{@Autowiredprivate TokenService tokenService;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws ServletException, IOException{LoginUser loginUser = tokenService.getLoginUser(request);if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication())){tokenService.verifyToken(loginUser);UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));// SpringSecurity 将当前登录用户的认证信息存到安全上下文中(SpringSecurity判断有没有登录的标志就是看安全上下文中有没有持有认证信息)SecurityContextHolder.getContext().setAuthentication(authenticationToken);}chain.doFilter(request, response);}
}
http://www.hkea.cn/news/431285/

相关文章:

  • 女性门户网站源码百度指数功能有哪些
  • 怎么帮公司做网站建设谷歌搜索引擎免费入口 香港
  • 请写出网站建设前期需要做的准备外贸定制网站建设电话
  • 南京门户网站建设网络营销优秀案例
  • 2012服务器如何做网站周口网络推广哪家好
  • 贵阳搜索玩的网站网络舆情软件免费入口
  • 前端自己写代码建网站要花多少钱游戏推广在哪里接活
  • 网站建设中+网页代码nba最新排名东西部
  • 东莞企业建设网站官网有限公司百度推广深圳分公司
  • 海外推广工作内容搜索引擎优化seo是什么
  • wordpress 发短信西安网络优化大的公司
  • dreamweaver个人网站南宁求介绍seo软件
  • 网站常用素材企业培训视频
  • 北京市通州区建设委员会网站网站新站整站排名
  • 太原网站推广只选中联传媒推广排名seo
  • 企业网站建设的常见流程为百度互联网营销顾问
  • 养殖企业网站网络营销策划名词解释
  • 如何进行电子商务网站推广?百度网盘app
  • 做情趣网站需要什么资质sem推广外包
  • 国外网站做任务赚钱的最近新闻有哪些
  • 建设部网站查资质中裕隆百度推广登录平台网址
  • 黄页网站大全免费山东网络推广优化排名
  • 网站文字代码常见的网络营销工具
  • 计算机毕设网站建设怎么改长沙网站设计拓谋网络
  • 类似红盟的网站怎么做aso优化推广
  • vs2013做网站怎样制作免费网页
  • b2c网站的开发无锡网络优化推广公司
  • 网站做视频在线观看营销活动推广方案
  • wordpress多站点统计google图片搜索引擎入口
  • 麻章手机网站建设百度网盘提取码入口