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

新手建设网站步骤视频营销

新手建设网站步骤,视频营销,专业外贸网站建设 诚信 青岛,电销系统多少钱一套目标和需求 我们的目的是在 SpringBootVue.js 这样的前后端分离的项目中增加一个登录权限控制模块。这个模块的需求如下: 包含多个角色,每个角色所具有的权限不同(可以看到不同的菜单和页面)对整个系统做登录控制,即…

目标和需求

我们的目的是在 SpringBoot+Vue.js 这样的前后端分离的项目中增加一个登录权限控制模块。这个模块的需求如下:

  1. 包含多个角色,每个角色所具有的权限不同(可以看到不同的菜单和页面)
  2. 对整个系统做登录控制,即未登录强制跳转到登录页面
  3. 登出功能

实现方案:
登录控制使用 Spring Security 框架,登录控制使用 JWT 实现,登录成功后使用 JWT 生成 token 返回前端,前端所有请求都在 cookie 中带上 token 到后端校验。
在这里插入图片描述

Spring Security原理

概述

Spring Security,这是一种基于 Spring AOP 和 Servlet 过滤器的安全框架。它提供全面的安全性解决方案,同时在 Web 请求级和方法调用级处理身份确认和授权。

框架原理

Spring Security 中主要通过 Filter 拦截 http 请求实现权限控制。

以下为框架自带主要过滤器:

  1. WebAsyncManagerIntegrationFilter
  2. SecurityContextPersistenceFilter
  3. HeaderWriterFilter
  4. CorsFilter
  5. LogoutFilter
  6. RequestCacheAwareFilter
  7. SecurityContextHolderAwareRequestFilter
  8. AnonymousAuthenticationFilter
  9. SessionManagementFilter
  10. ExceptionTranslationFilter
  11. FilterSecurityInterceptor
  12. UsernamePasswordAuthenticationFilter
  13. BasicAuthenticationFilter

框架核心组件如下:

  1. SecurityContextHolder:提供对SecurityContext的访问
  2. SecurityContext:持有Authentication对象和其他可能需要的信息
  3. AuthenticationManager 其中可以包含多个AuthenticationProvider
  4. ProviderManager对象为AuthenticationManager接口的实现类
  5. AuthenticationProvider:主要用来进行认证操作的类 调用其中的authenticate()方法去进行认证操作
  6. Authentication:Spring Security方式的认证主体
  7. GrantedAuthority:对认证主题的应用层面的授权,含当前用户的权限信息,通常使用角色表示
  8. UserDetails:构建Authentication对象必须的信息,可以自定义,可能需要访问DB得到
  9. UserDetailsService:通过username构建UserDetails对象,通过loadUserByUsername根据userName获取UserDetail对象

根据业务需求,这里我们继承UsernamePasswordAuthenticationFilter自定义过滤器作为后端拦截登录请求的过滤器。

由于Spring Security没有自带解析 token 的过滤器,因此我们需要自己实现对 JWT 适配的鉴权过滤器,通过继承 BasicAuthenticationFilter实现自定义鉴权过滤器。

自定义安全配置

通过实现WebSecurityConfigurerAdapter中的configure(HttpSecurity http),可以自定义安全配置,比如装配自定义过滤器,设置除部分请求外均需要鉴权,设置一些回调Handler等。

JWT原理

JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。

其原理是将用户信息的JSON字符串加密生成唯一的token返回给前端,后端通过解析token来验证是否已登录。

模块实现

数据库表设计

一共涉及四个表,分别为用户表,角色表,菜单表以及用户角色关联表。

其中角色与菜单一一对应。

前端实现

前端使用Vue.js+Element-UI实现,对于菜单的存储,使用了Element-UI中的树形组件产生的value值,实际为一个JSON字符串,前端通过获取该字符串,解析得到菜单信息,显示具体的菜单按钮。

token使用cookie保存,浏览器会自动将cookie携带在每一个请求中。

toFirstPage(level) {//根据角色level选择进入默认页面if(level === '999'){this.$router.push({ path: "/enterpriseManage" });}else if(level === '800'){this.$router.push({ path: "/enterpriseAccount" });}else{this.$router.push({ path: "/extAccount" });}},
async checkLogin(loginUser){try {let username = this.loginUser.username;var res = await checkUsernameAndPassword({username: username,password: this.loginUser.password,});if(res.resultCode == '0'){window.name =  this.$moment(new Date()).format("YYYY-MM-DD HH:mm:ss");//全局缓存登录的用户信息this.$store.baseStore.commit('setUserInfo', res.result);this.$store.baseStore.commit('setWindowname',  window.name);if(res.result.managerLevel ==='999'){this.$store.baseStore.dispatch('getAllDeptId');}this.toFirstPage(res.result.managerLevel);} else {this.$message({type: 'error',message: res.result});}} catch (error) {this.$message({type: 'error',message: error});}
},

上面的代码是前端发送登录请求的方法,具体请求路径保存在checkUsernameAndPassword变量中,登录通过后,通过调用baseStore中的方法存储登录信息,并且根据角色跳转到对应的路由中。

baseStore中的部分方法如下,

Vue.use(Vuex);
export const baseStore = new Vuex.Store({//全局缓存state: {userInfo:{},},mutations: {setUserInfo(state, payload) {//保存到浏览器缓存window.localStorage.setItem("userInfo", JSON.stringify(payload));state.userInfo = payload;},},getters: {getUserInfo: state => {if(state.userInfo == undefined || state.userInfo.username == undefined){var userInfo = window.localStorage.getItem("userInfo");if(userInfo == undefined){return new Object();}else{state.userInfo=JSON.parse(userInfo);return state.userInfo;}}else{return state.userInfo}},},
});

在登录成功进入到默认页面之前,我们需要解析登录信息,得到菜单信息以显示特定的菜单。

menu.vuecreated() {// 得到登录信息let userInfo = this.$store.baseStore.getters.getUserInfo;//从菜单信息中得到一级菜单信息let menu = userInfo.menu.firstmenuset;//逐个查找菜单项是否在firstmenuset中if(menu.indexOf("账号详情") != -1){this.$data.items.push({ topage: '/extAccount', userName: 'iconfont ucc-shouye2 flew-left-menuicon', text: '账号详情', modelName: 'extAccount', });}
},

除了登录成功之后的操作外,登录失败则跳转到登录页面,前面代码中我们的登录请求是这样发送的:

login.vueimport {checkUsernameAndPassword,
}from '@/api/getData';const res = await checkUsernameAndPassword({username: username,password: this.loginUser.password,});

checkUsernameAndPassword 是从getData.js中导入的

getData.jsimport fetch from '@/config/fetch'
export const checkUsernameAndPassword = (args) => fetch('/login', args, 'POST');

这里的fetch方法实际上是所有请求发送的方法,我们可以在这里首先解析后端返回码,若为未登录,则跳转到登录页面:

import { baseUrl } from './env'
import router from '../router'
export default async(url = '', data = {}, type = 'GET', method = 'fetch') => {//省略其他代码......let requestConfig = {credentials: 'include',method: type,headers: {'Accept': 'application/json','Content-Type': 'application/x-www-form-urlencoded;charset=utf-8'},mode: "cors",cache: "no-cache"}if (type == 'POST') {requestConfig.body=dataStr;}try {const response = await fetch(url, requestConfig);const responseJson = await response.json();if(responseJson.resultCode == "00015"){router.push("login");}else{return responseJson;}} catch (error) {throw new Error(error);}......}

后端实现

后端我们需要实现:

  1. 登录过滤器JWTLoginFilter
  2. 请求鉴权器JWTAuthenticationFilter
  3. 登录认证器CustomAuthenticationProvider
  4. 自定义配置SecurityConfig
  5. 鉴权失败Handler:GoAuthenticationEntryPoint
  6. 登录成功Handler:GoAuthenticationSuccessHandler

首先要准备基础设施,相关的Bean,验证账号密码的Service以及token的生成等。需要注意的是,用户信息Bean必须继承Spring Security中的UserDetails。Service需要实现UserDetailsService中的loadUserByUsername(String userName)方法。

这里只贴token的生成:

public class JWTTokenUtil {public static final String SECRET = "spring security Jwt Secret";public static final String BEARER = "Bearer:";public static final String AUTHORIZATION = "Authorization";public static String getToken(JSONObject user) {return Jwts.builder().setSubject(JSONObject.toJSONString(user)).setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 24 * 1000)).signWith(SignatureAlgorithm.HS512, SECRET).compact();}}

登录过滤器,继承Spring Security自带的用户名密码过滤器,实现对登录请求的拦截和转发。

public class JWTLoginFilter extends UsernamePasswordAuthenticationFilter {private AuthenticationManager authenticationManager;public JWTLoginFilter(AuthenticationManager authenticationManager) {this.authenticationManager = authenticationManager;}// 接收并解析用户凭证@Overridepublic Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res)throws AuthenticationException {User user = new User();user.setUsername(req.getParameter("username").trim());user.setPassword(req.getParameter("password"));return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));}}

请求鉴权器,拦截所有请求,从cookie中查询token信息,并进行解析鉴定。

public class JWTAuthenticationFilter extends BasicAuthenticationFilter {public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {super(authenticationManager);}@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)throws IOException, ServletException {Cookie [] cookies = request.getCookies();String authorization = "";if(cookies != null){for(Cookie cookie : cookies){if(JWTTokenUtil.AUTHORIZATION.equals(cookie.getName())){authorization = cookie.getValue();}}}if ("".equals(authorization)) {chain.doFilter(request, response);return;}UsernamePasswordAuthenticationToken authentication = getAuthentication(authorization);if(authentication == null){chain.doFilter(request, response);return;}//保存到spring security上下文中SecurityContextHolder.getContext().setAuthentication(authentication);chain.doFilter(request, response);}private UsernamePasswordAuthenticationToken getAuthentication(String authorization) {// parse the token.try {String userJson = Jwts.parser().setSigningKey(JWTTokenUtil.SECRET).parseClaimsJws(authorization.replace(JWTTokenUtil.BEARER, "")).getBody().getSubject();User user = JSONObject.parseObject(userJson, User.class);if (user != null) {return new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());}} catch (MalformedJwtException | ExpiredJwtException e) {//token解析失败,token过期return null;}return null;}
}

登录认证器,负责将登录过滤器拦截得到的登录账号密码进行验证。

public class CustomAuthenticationProvider implements AuthenticationProvider {private final UserDetailsService service;  public CustomAuthenticationProvider(UserDetailsService userDetailsService) {  this.service = userDetailsService;}  /*** 验证类*/@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) authentication;String username = token.getName();User userDetails = null;  if(username != null) {  //调用相应service从数据库获取对应用户信息userDetails = (User) service.loadUserByUsername(username);  } if(userDetails == null) {  throw new UsernameNotFoundException("用户名或密码无效");  }else if (!userDetails.isEnabled()){  throw new DisabledException("用户已被禁用");  }else if (!userDetails.isAccountNonExpired()) {  throw new AccountExpiredException("账号已过期");}else if (!userDetails.isAccountNonLocked()) {  throw new LockedException("账号已被锁定");  }else if (!userDetails.isCredentialsNonExpired()) {  throw new LockedException("凭证已过期");  }String password = userDetails.getPassword();if(!password.equals(Md5.encodeByMD5((String)token.getCredentials()))) {  throw new BadCredentialsException("用户名/密码无效");  } return new UsernamePasswordAuthenticationToken(userDetails, password,userDetails.getAuthorities());}@Overridepublic boolean supports(Class<?> authentication) {return UsernamePasswordAuthenticationToken.class.equals(authentication);}}

登录成功和失败的回调处理器,可以在这两个处理器中实现cookie的存储,失败状态码的返回等

public class GoAuthenticationEntryPoint implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)throws IOException, ServletException {Result res = null;response.setCharacterEncoding("UTF-8");if(exception instanceof InsufficientAuthenticationException){res = new Result("00015",Result.FAILURE,exception.getMessage());}else{res = new Result("00010",Result.FAILURE,"未知权限错误");}response.setContentType("application/json; charset=utf-8");PrintWriter out = null;try {out = response.getWriter();out.write(JSONObject.toJSONString(res));} catch (IOException e) {e.printStackTrace();} finally {if (out != null) {out.close();}}}}
public class GoAuthenticationSuccessHandler implements AuthenticationSuccessHandler  {@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)throws IOException, ServletException {User user = (User)authentication.getPrincipal();//返回前端的tokenJSONObject userToken = new JSONObject();userToken.put("username", user.getUsername());cookie.setPath("/ucc");response.setCharacterEncoding("UTF-8");response.setContentType("application/json; charset=utf-8");response.addCookie(cookie);response.addCookie(new Cookie(JWTTokenUtil.AUTHORIZATION, JWTTokenUtil.BEARER + JWTTokenUtil.getToken(userToken)));Result result = new Result("0",Result.SUCCESS,user);PrintWriter out = null;try {out = response.getWriter();out.write(JSONObject.toJSONString(result));} catch (IOException e) {e.printStackTrace();} finally {if (out != null) {out.close();}}}}

最后是Spring Security的自定义配置类,将配置一些权限管理的规则以及整合上面各项功能类。

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class securityConfig extends WebSecurityConfigurerAdapter {@AutowiredUserDetailsService service;@Bean  public AuthenticationProvider authenticationProvider(){  AuthenticationProvider authenticationProvider=new CustomAuthenticationProvider(service);  return authenticationProvider;}/*** 验证用户权限的方法*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.authenticationProvider(authenticationProvider()); }@Overrideprotected void configure(HttpSecurity http) throws Exception {JWTLoginFilter jwtLoginFilter= new JWTLoginFilter(authenticationManager());JWTAuthenticationFilter authenticationFilter = new JWTAuthenticationFilter(authenticationManager());//设置回调HandlerjwtLoginFilter.setAuthenticationSuccessHandler(new GoAuthenticationSuccessHandler());http.cors().and().csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().exceptionHandling()  //异常处理.authenticationEntryPoint(new GoAuthenticationEntryPoint()).and().authorizeRequests().antMatchers().permitAll()//可以设置不需要认证的请求.anyRequest().authenticated().and().addFilter(jwtLoginFilter).addFilter(authenticationFilter).logout() //拦截登出.logoutUrl("/logout")//登出URL.logoutSuccessHandler(new GoLogoutSuccessHandler()) //登出成功回调函数.invalidateHttpSession(true).deleteCookies(JWTTokenUtil.AUTHORIZATION);}}
http://www.lbrq.cn/news/2656531.html

相关文章:

  • qq电脑版官方入口宁波网络推广优化方案
  • pycharm 做网站哪个好一站式营销平台
  • 京东商城网站建设策划书推广技术
  • 推荐微信网站建设站长之家seo查询官方网站
  • 推荐武汉手机网站设计搜索关键词排名查询
  • 网站的robots.txt文件新网站友链
  • 哪个网站做国内销海外的app注册推广平台
  • 免费网站建设推广页面优化的方法
  • 北京网站建设模板主题百度主页入口
  • 如何做网站标题wordpress seo教程
  • 建筑焊工证查询网站官方网微营销推广平台有哪些
  • 怎么做图片网站江门关键词优化公司
  • 重庆公司黄页企业名录seo代码优化有哪些方法
  • 电商有哪些公司百度seo排名推广
  • 南京市溧水建设局网站网络营销十大成功案例
  • 做境外域名网站seo好学吗入门怎么学
  • 网站的收费窗口怎么做七台河网站seo
  • 简历生成网站网站快速排名推荐
  • 西安市做网站公司无锡seo公司找哪家好
  • 台州市建站公司国家高新技术企业查询
  • 自己做微商想做个网站磁力搜索引擎2023
  • 建设网站项目的目的站长统计app软件
  • 网站建设模板怎么做制作网站的步骤是什么
  • 一些常用的网站曼联vs曼联直播
  • 网站排名优化如何做南宁网络推广品牌
  • 视频推广网站安徽seo优化规则
  • 哪家做网站好 成都合肥网络推广优化公司
  • 做轻奢品的电商网站深圳百度关键字优化
  • 池州网站seo为什么打开网址都是站长工具
  • dw网站引导页怎么做百度推广平台有哪些
  • MySQL 子查询
  • 算法_python_牛客华为机试笔记_01
  • 数据结构(一)顺序表
  • Visual Studio Code (v1.103) 中 GitHub Copilot 最新更新!
  • 柠檬笔试——野猪骑士
  • 【JAVA EE初阶】多线程(进阶)