Spring Boot + Vue的网上商城之springsecurity+jwt+redis实现用户权限认证实现

Spring Boot + Vue的网上商城之springsecurity+jwt+redis实现用户权限认证实现

在网上商城项目中,用户的安全性是非常重要的。为了实现用户权限认证和安全校验,我们可以使用Spring Security、JWT和Redis来实现。本篇博客将详细介绍后端和前台的实现过程,并提供相应的代码案例。

思路

当用户点击登录按钮时,前端发送一个POST请求到后端的登录接口,传递用户名和密码。后端接收到请求后,验证用户名和密码的正确性。如果验证通过,后端生成一个JWT(JSON Web Token),并将其返回给前端。

前端接收到JWT后,将其存储在本地,例如使用localStorage。然后通过Vue Router进行页面跳转,跳转到需要进行权限校验的页面。

在需要进行权限校验的页面组件中,可以在created钩子函数中检查本地存储中是否存在JWT。如果不存在,则表示用户未登录或登录已过期,可以通过Vue Router跳转到登录页面。

需要注意的是,在每次向后端发送请求时,需要将JWT作为请求头的Authorization字段进行传递,以便后端进行权限校验。

后端在接收到请求时,可以通过解析JWT来验证用户的身份和权限。JWT中通常包含用户ID、用户名、权限信息等。后端可以使用Spring Security的相关功能进行JWT的解析和校验。

总结来说,用户登录和权限认证的流程可以简化为以下几个步骤:

  1. 用户在前端页面输入用户名和密码,并点击登录按钮。
  2. 前端发送POST请求到后端的登录接口,传递用户名和密码。
  3. 后端验证用户名和密码的正确性,如果验证通过,生成JWT并返回给前端。
  4. 前端接收到JWT后,将其存储在本地。
  5. 前端通过Vue Router进行页面跳转,跳转到需要进行权限校验的页面。
  6. 在需要进行权限校验的页面组件中,检查本地存储中是否存在JWT,如果不存在,则跳转到登录页面。
  7. 在每次向后端发送请求时,将JWT作为请求头的Authorization字段进行传递。
  8. 后端在接收到请求时,解析JWT并进行权限校验,校验通过则返回相应的数据或页面。

后端实现

Spring Security配置

首先,在后端的Spring Boot项目中,我们需要配置Spring Security来实现用户权限认证。我们可以创建一个SecurityConfig类来配置Spring Security。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate UserService userService;@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable().authorizeRequests().antMatchers("/api/public/**").permitAll().anyRequest().authenticated().and().addFilter(new JwtAuthenticationFilter(authenticationManager())).addFilter(new JwtAuthorizationFilter(authenticationManager(), userService)).sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userService).passwordEncoder(passwordEncoder());}@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}

上述代码中,我们配置了允许访问/api/public/**路径的请求,其他请求需要进行认证。我们还添加了两个过滤器JwtAuthenticationFilterJwtAuthorizationFilter来处理JWT的认证和授权。

JWT认证和授权过滤器

接下来,我们来实现JWT的认证和授权过滤器。

public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {private AuthenticationManager authenticationManager;public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {this.authenticationManager = authenticationManager;setFilterProcessesUrl("/api/login");}@Overridepublic Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {try {UserCredentials credentials = new ObjectMapper().readValue(request.getInputStream(), UserCredentials.class);return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(credentials.getUsername(), credentials.getPassword(), new ArrayList<>()));} catch (IOException e) {throw new RuntimeException(e);}}@Overrideprotected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {String token = Jwts.builder().setSubject(((User) authResult.getPrincipal()).getUsername()).setExpiration(new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME)).signWith(SignatureAlgorithm.HS512, SecurityConstants.SECRET).compact();response.addHeader(SecurityConstants.HEADER_STRING, SecurityConstants.TOKEN_PREFIX + token);}
}
public class JwtAuthorizationFilter extends BasicAuthenticationFilter {private UserService userService;public JwtAuthorizationFilter(AuthenticationManager authenticationManager, UserService userService) {super(authenticationManager);this.userService = userService;}@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {String header = request.getHeader(SecurityConstants.HEADER_STRING);if (header == null || !header.startsWith(SecurityConstants.TOKEN_PREFIX)) {chain.doFilter(request, response);return;}UsernamePasswordAuthenticationToken authentication = getAuthentication(request);SecurityContextHolder.getContext().setAuthentication(authentication);chain.doFilter(request, response);}private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {String token = request.getHeader(SecurityConstants.HEADER_STRING);if (token != null) {String username = Jwts.parser().setSigningKey(SecurityConstants.SECRET).parseClaimsJws(token.replace(SecurityConstants.TOKEN_PREFIX, "")).getBody().getSubject();if (username != null) {User user = userService.loadUserByUsername(username);return new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());}return null;}return null;}
}

上述代码中,JwtAuthenticationFilter处理登录请求,将用户的认证信息封装为JWT,并添加到响应头中。JwtAuthorizationFilter处理其他请求,从请求头中获取JWT并进行认证和授权。

用户服务和认证

为了实现用户的认证和授权,我们需要创建一个用户服务实现类UserService

@Service
public class UserService implements UserDetailsService {@Autowiredprivate UserRepository userRepository;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {User user = userRepository.findByUsername(username);if (user == null) {throw new UsernameNotFoundException(username);}return user;}
}

上述代码中,我们通过用户名从数据库中获取用户信息。

Redis存储Token

为了增加用户登录的安全性,我们可以将JWT存储到Redis中,并设置过期时间。

@Service
public class TokenService {private RedisTemplate<String, Object> redisTemplate;public TokenService(RedisTemplate<String, Object> redisTemplate) {this.redisTemplate = redisTemplate;}public void saveToken(String username, String token) {redisTemplate.opsForValue().set(username, token, SecurityConstants.EXPIRATION_TIME, TimeUnit.MILLISECONDS);}public boolean validateToken(String username, String token) {String storedToken = (String) redisTemplate.opsForValue().get(username);return storedToken != null && storedToken.equals(token);}public void deleteToken(String username) {redisTemplate.delete(username);}
}

上述代码中,我们使用redisTemplate将用户名和JWT存储到Redis中,并设置过期时间。在校验Token时,我们从Redis中获取存储的Token进行比较。

前台实现

在前台,我们使用Vue来实现用户登录和权限认证的功能。我们需要创建相应的组件和路由来实现用户登录和权限校验。

登录组件

<template><div><h1>用户登录</h1><form @submit.prevent="login"><label for="username">用户名:</label><input type="text" id="username" v-model="username" required><br><label for="password">密码:</label><input type="password" id="password" v-model="password" required><br><button type="submit">登录</button></form></div>
</template><script>
export default {data() {return {username: '',password: ''};},methods: {login() {// 调用后端API接口进行用户登录// 使用axios或其他HTTP库发送POST请求}}
};
</script>

路由配置

import Vue from 'vue';
import VueRouter from 'vue-router';
import Login from './components/Login.vue';
import ProductList from './components/ProductList.vue';Vue.use(VueRouter);const routes = [{ path: '/login', component: Login },{ path: '/products', component: ProductList, meta: { requiresAuth: true } }
];const router = new VueRouter({routes
});router.beforeEach((to, from, next) => {const token = localStorage.getItem('token');if (to.matched.some(record => record.meta.requiresAuth)) {if (!token) {next('/login');} else {next();}} else {next();}
});export default router;

在上述代码中,我们配置了两个路由,/login用于用户登录,/products用于展示商品列表。在/products路由中,我们设置了requiresAuthtrue,表示需要进行权限校验。在路由导航守卫中,我们检查是否存在Token,如果不存在则跳转到登录页面。

入口文件

import Vue from 'vue';
import App from './App.vue';
import router from './router';new Vue({el: '#app',router,render: h => h(App)
}).$mount('#app');

在入口文件中,我们创建了一个Vue实例,并将路由配置和根组件传入。然后将Vue实例挂载到#app元素上。

用户登录

在登录组件中,我们需要调用后端API接口进行用户登录,并将返回的Token保存到本地存储中。

methods: {login() {axios.post('/api/login', {username: this.username,password: this.password}).then(response => {const token = response.data.token;localStorage.setItem('token', token);this.$router.push('/products');}).catch(error => {console.error(error);});}
}

在上述代码中,我们使用axios库发送POST请求到后端的登录接口。如果登录成功,会返回一个包含Token的响应。我们将Token保存到本地存储中,并使用$router.push方法跳转到商品列表页面。

权限校验

在商品列表组件中,我们需要进行权限校验,只有在用户登录成功并且存在Token的情况下才能访问该页面。

export default {created() {if (!localStorage.getItem('token')) {this.$router.push('/login');}}
};

在上述代码中,我们在组件创建时检查本地存储中是否存在Token,如果不存在则跳转到登录页面。

总结

本文介绍了如何使用Spring Security和Vue实现用户登录和权限认证的功能。通过使用JWT和Redis存储Token,我们可以实现无状态的用户认证,提高系统的可扩展性和安全性。同时,通过使用Vue的路由导航守卫,我们可以实现前端的权限校验,确保只有登录用户才能访问受限资源。希望本文能对你理解和实现用户登录和权限认证功能有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/82705.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue3 菜鸟入门(三)超详细:引用外部依赖、组件、路由

【学习笔记】Vue3 菜鸟入门&#xff08;三&#xff09;超详细&#xff1a;引用外部依赖、组件、路由 关键词&#xff1a;Vue 、Vue 3、Java、Spring Boot、Idea、数据库、一对一、培训、教学本文主要内容含Vue 基本框架 模板语法、指令计划1小时完成&#xff0c;请同学尽量提前…

计算机是如何工作的(上篇)

计算机发展史 世界上很多的高科技发明,来自于军事领域 计算机最初是用来计算弹道导弹轨迹的 弹道导弹 ~~国之重器,非常重要 两弹一星 原子弹,氢弹,卫星(背后的火箭发射技术) 计算弹道导弹轨迹的计算过程非常复杂,计算量也很大 ~~ 但是可以手动计算出来的(当年我国研究两弹一…

Python py文件打包成 exe文件

文章目录 安装 pyinstaller 模块pyinstaller 的使用pyinstaller 常用参数多文件打包 安装 pyinstaller 模块 pip install pyinstaller -i https://pypi.tuna.tsinghua.edu.cn/simple在 pyinstaller 模块安装成功之后&#xff0c;在 Python 的安装目录下的 Scripts 目录下会增加…

二叉树实现的相关函数

1.二叉树的创建 BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi) { if (n0||a[*pi] #){ (*pi);return NULL;}BTNode* root (BTNode*)malloc(sizeof(BTNode));root->_data a[(*pi)];root->_left BinaryTreeCreate(a, --n, pi);root->_right Binary…

解决VS Code安装远程服务器插件慢的问题

解决VS Code安装远程服务器插件慢的问题 最近想在服务器上做juypter notebook的代码运行&#xff0c;发现要给服务器安装Jupyter插件&#xff0c;但是安装速度奇慢无比&#xff08;因为服务器不连外网&#xff09;&#xff0c;一开始查看从VS Code插件市场下载插件的博客&…

ip地址怎么改网速快

在当今高度依赖互联网的时代&#xff0c;快速稳定的网络连接对于人们的生活和工作至关重要。然而&#xff0c;有时我们可能会遇到网络速度缓慢的问题。虽然更改IP地址并不能直接影响网络速度&#xff0c;但它可以成为改善网络连接的一种策略之一。虎观代理小二二将探讨如何通过…

Apache Spark 在爱奇艺的应用实践

01 Apache Spark 在爱奇艺的现状 Apache Spark 是爱奇艺大数据平台主要使用的离线计算框架&#xff0c;并支持部分流计算任务&#xff0c;用于数据处理、数据同步、数据查询分析等场景&#xff1a; 数据处理&#xff1a;在数据开发平台中支持开发者提交 Spark Jar 包任务或Spar…

Mac node nvm 切换版本,指定版本

一、Homebrew自动安装 // Homebrew安装 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)" // Homebrew卸载 /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/HomebrewUninstall.sh)&quo…

macOS 运行xxx.command文件提示”无法执行,因为您没有正确的访问权限“解决方法

使用苹果mac电脑运行.command文件时&#xff0c;是否遇到弹出”无法执行&#xff0c;因为您没有正确的访问权限“的窗口&#xff1f;遇到这种问题怎么解决呢&#xff1f;这里小编为大家带来了详细的解决方法&#xff0c;一起来看看吧&#xff01; 解决方法&#xff1a; 方法一…

matlab 间接平差法拟合二维圆

目录 一、算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。爬虫自重。 一、算法原理 圆的方程为: ( x - x 0 )

PG数据恢复must be member of role “xxxx“

背景&#xff1a;有一份数据库备份文件&#xff0c;sql语句中包含了drop语句。postgresql数据中有一个模式&#xff1a;test_schema&#xff0c;owner是test_schema_onwer。有另外一个用户test_username2。test_username2具有test_schema的所有权限。 test_username2才是操作te…

GO学习之 远程过程调用(RPC)

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 8、GO学习之 函数(Function) 9、GO学习之 接口(Interface) 10、GO学习之 网络通信(Net/Htt…

SqlBulkCopy - 批量写入数据库

SqlBulkCopy 是 ADO.NET 中的一种类&#xff0c;它提供了高性能的批量数据插入功能。SqlBulkCopy 类位于 System.Data.SqlClient 命名空间中&#xff0c;并且适用于使用 SQL Server 数据库。 ADO.NET 是 Microsoft .NET Framework 的一部分&#xff0c;提供了与数据存储的连接…

怎么为Web服务器配置虚拟主机?【步骤演示】

在安装了Web服务器Apache后&#xff0c;为了更好地使用Apache&#xff0c;还需要学习如何对Apache进行配置。在项目开发中&#xff0c;经常需要配置虚拟主机和访问权限&#xff0c;下面对Web服务器的配置进行详细讲解。 配置虚拟主机 在默认情况下&#xff0c;Apache只有Chwe…

Java手写双向广度优先和双向广度优先应用拓展案例

Java手写双向广度优先和双向广度优先应用拓展案例 1. 算法思维 思维如下&#xff1a; 双向广度优先搜索算法 (Bidirectional Breadth-First Search)1. 初始化起始节点和目标节点的队列和访问集合 2. 初始化起始节点和目标节点的距离为0 3. 初始化起始节点和目标节点的父节点…

ssh服务登录原理与配置

文章目录 前言一、基于口令的认证&#xff08;用户名密码&#xff09;二、基于公钥的认证&#xff08;免密登录&#xff09;三、禁止用户登录和修改端口四、免密登录具体操作 前言 非对称加密是在认证用户连接的时候使用的&#xff0c;对称加密是在用户连接之后开始传输数据的…

高端知识竞赛中用到的软件和硬件有哪些

现在单位搞知识竞赛&#xff0c;已不满足于用PPT放题&#xff0c;找几个简单的抢答器、计分牌弄一下了&#xff0c;而是对现场效果和科技感要求更高了。大屏要分主屏侧屏&#xff0c;显示内容要求丰富炫酷&#xff1b;选手和评委也要用到平板等设备&#xff1b;计分要大气些&am…

ES6(三)

文章目录 Promise概念作用回调地狱Promise使用对象的状态Promise.allPromise.race Generator 函数概念基本语法异步流程 Class语法类的写法getter与setter静态属性和静态方法继承模块化 Promise 概念 Promise 是异步编程的一种解决方案&#xff0c;比传统的解决方案回调函数,…

【JavaEE】多线程案例-单例模式

文章目录 1. 前言2. 什么是单例模式3. 如何实现单例模式3.1 饿汉模式3.2 懒汉模式4. 解决单例模式中遇到的线程安全问题4.1 加锁4.2 加上一个判断解决频繁加锁问题4.2 解决因指令重排序造成的线程不安全问题 1. 前言 单例模式是我们面试中最常考到的设计模式。什么是设计模式呢…

苹果电脑 m1 apple silican docker 安装 redis 6.2

安装环境&#xff1a; 苹果电脑&#xff0c;m1, apple silican, 系统版本13.5.2&#xff0c;32G内存 docker版本&#xff1a;4.15.0 redis版本&#xff1a;6.2&#xff0c;arm 64位 (https://hub.docker.com/) redis.conf 下载地址&#xff1a;https://redis.io/docs/manag…