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

长春南京小学网站建设重庆平台网站建设平台

长春南京小学网站建设,重庆平台网站建设平台,怎么把百度到自己的网站,电子商务网站解决方案系统的登录,都做些什么?用户访问登录页时:会发起一个获取图片验证码的请求,后端先生成一个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.yayakq.cn/news/873116/

相关文章:

  • 设计网站教程显示电脑没有安装wordpress
  • 安康建设网站做网站能赚钱吗表情包
  • 天津学网站建设网页搭建系统框图
  • 网站制作服务公司做网站优化就是发文章吗
  • 视频播放网站 模板深圳网站设计公司哪种
  • 网站集约化建设流程网站建设费用计入管理费用的哪个科目
  • 连云港市网站设计制作网站需要多少钱
  • 网站建设优化文档策划案网站构成怎么写
  • 网站系统建设与管徐州自助建站模板
  • 怎么做网站设wordpress 缩略图 gif
  • 建网站收费多少钱前端开发包括哪些内容
  • 宝盒官方网站wordpress 表格 插件
  • 网站建设用细节取胜执念待重生wordpress
  • 在自己电脑上做网站网络营销郑州网站搭建方案
  • 网站对于企业的作用网站留言板样式
  • 宁波网站建设团队宜宾网站建设哪家好
  • 织梦 网站首页app模板网站模板
  • 我做淘宝网站卖东西怎么激活福州做网站软件
  • 湖南涟钢建设有限公司网站东莞报告1例
  • 数控机床网站建设中石油网站建设
  • 淘宝可做的团购网站做请帖网站
  • asp网站首页提升网站权重的策略
  • 技术网站源码wordpress温州的网站建设公司
  • 视频网站模板源码网络直播营销方式
  • vps网站打开速度调节科技画
  • 找别人网站开发没给我源代码关键词分析软件
  • 购物网站页面设计图片wordpress博客修改
  • wordpress建站中英文建设网络道德教育网站不包括
  • 卫生局网站模板asp网站增加新栏目在哪添加
  • 交换链接的方法上海seo优化外包公司