使用SpringSecurity实现登录及鉴权

介绍

前一段时间公司要求登录和鉴权使用SpringSecurity,看了很多都感觉不太适合企业开发,于是自己整理了一下,基于@PreAuthorize注解鉴权,大大的方便的权限控制。

设计技术

本项目使用mysql数据库、mybatis-plus、redis缓存、jwt、hutool工具包、fastjson2。

Maven

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!--        数据库相关--><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3</version></dependency><!--        lombook--><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><!--        hutool--><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.15</version></dependency><!--redis--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><version>2.6.13</version></dependency><!--security--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!--jwt依赖--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.0</version></dependency><!--JSON解析工具--><dependency><groupId>com.alibaba.fastjson2</groupId><artifactId>fastjson2</artifactId><version>2.0.10</version></dependency>

数据库

需要四张表,如下图:

sys_user(用户表)

在这里插入图片描述

sys_role(角色表)

在这里插入图片描述

sys_permission(权限表)

在这里插入图片描述

sys_user_role(用户角色表)

在这里插入图片描述

搭建环境

自己搭建哦!!

配置类

import com.qian.chatgpt.entity.info.SecurityInfo;
import com.qian.chatgpt.handler.AuthenticationHandler;
import com.qian.chatgpt.handler.CustomLogoutHandler;
import com.qian.chatgpt.handler.CustomLogoutSuccessHandler;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;/*** @author Qiansheng* @date   2023/4/23* @description security配置类*/
@EnableGlobalMethodSecurity(prePostEnabled = true) //开启权限注解全局安全认证
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class SecurityConfig extends WebSecurityConfigurerAdapter {private final UserDetailsService userDetailsService;private final AuthenticationHandler authenticationHandler;private final com.qian.chatgpt.filter.AuthenticationTokenFilter AuthenticationTokenFilter;private final SecurityInfo securityInfo;@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService);}@Overrideprotected void configure(HttpSecurity http) throws Exception {String[] anonymouPaths = securityInfo.getPermitAllPaths().toArray(new String[0]);http// CSRF禁用,因为不使用session.csrf().disable()// 认证失败处理类,指定异常处理实现类.exceptionHandling().authenticationEntryPoint(authenticationHandler).and()// 基于token,所以不需要session.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()// 过滤请求.authorizeRequests()//设置匿名访问.antMatchers(anonymouPaths).permitAll()//其他全部拦截认证.anyRequest().authenticated().and().logout().addLogoutHandler(new CustomLogoutHandler()).logoutSuccessHandler(new CustomLogoutSuccessHandler());//将认证过滤器添加到security中http.addFilterBefore(AuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);}/*** 设置加密方式** @return*/@Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}

是不是有很多爆红呢?问题比大,我们一个一个来

UserDetailsService:此类是用来从数据库查询用户信息的

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.qian.chatgpt.entity.user.SysPermission;
import com.qian.chatgpt.entity.user.SysUser;
import com.qian.chatgpt.entity.user.SysUserRole;
import com.qian.chatgpt.mapper.SysUserMapper;
import com.qian.chatgpt.service.user.ISysPermissionService;
import com.qian.chatgpt.service.user.ISysUserRoleService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;import java.util.List;/*** @author : Qiansheng* @创建时间 : 2023/4/23* @描述信息 : security 对比用户名类*/
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class UserDetailsServiceImpl implements UserDetailsService {private final SysUserMapper sysUserMapper;private final ISysPermissionService ISysPermissionService;private final ISysUserRoleService sysUserRoleService;@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {SysUser user = sysUserMapper.selectOne(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUsername,username));//判断用户名是否存在 如存在就将信息存储if (user == null) {throw new UsernameNotFoundException("用户不存在: " + username);}String permissionList="";//查询权限SysUserRole userRole = sysUserRoleService.getOne(Wrappers.lambdaQuery(SysUserRole.class).eq(SysUserRole::getUserId, user.getId()));List<SysPermission> permissions = ISysPermissionService.list(Wrappers.lambdaQuery(SysPermission.class).eq(SysPermission::getRoleId, userRole.getRoleId()));for (SysPermission permission : permissions) {permissionList=permissionList+permission.getPermissionKey()+",";}if(permissionList.length()!=0){permissionList = permissionList.substring(0,permissionList.length()-1);}User user1 = new User(user.getUsername(), user.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList(permissionList));return user1;}
}

AuthenticationHandler:此类是用来处理认证失败的异常处理类

import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import com.qian.chatgpt.util.R;
import com.qian.chatgpt.util.ServletUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
/*** @author : Qiansheng* @创建时间:2023/4/23* @描述信息: security 拦截后返回内容*/
@Component
@Slf4j
public class AuthenticationHandler implements AuthenticationEntryPoint, Serializable {private static final long serialVersionUID = -8970718410437077606L;@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) {ServletUtil.renderString(HttpStatus.HTTP_FORBIDDEN, response, JSONUtil.toJsonStr(R.fail(HttpStatus.HTTP_FORBIDDEN, "非法请求:" +e.getMessage())));}
}

SecurityInfo: 放行路径信息实体

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;import java.util.Set;/*** @author   gqs* @date     2023/5/16 16:49* @description 放行路径信息实体*/
@Component
@ConfigurationProperties("security")
@Data
public class SecurityInfo {/*** 放行路径*/private Set<String> permitAllPaths;}

所有需要放行的路径放在yml配置文件中:
在这里插入图片描述

AuthenticationTokenFilter:用户请求认证拦截器

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.qian.chatgpt.util.JwtUtil;
import com.qian.chatgpt.util.RedisCache;
import io.jsonwebtoken.Claims;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** @author   gqs* @date     2023/5/16 16:49* @description 用户请求token认证拦截器*/
@Component
public class AuthenticationTokenFilter extends OncePerRequestFilter {@Resourceprivate RedisCache redisCache;@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {//获取tokenString token = request.getHeader("token");if (!StringUtils.hasText(token)) {//放行filterChain.doFilter(request, response);return;}//使用token从redis获取jwtString cacheObject = redisCache.getCacheObject(token);//使用jwt获取用户信息并处理Claims claims = null;try {claims = JwtUtil.parseJWT(cacheObject);} catch (Exception e) {e.printStackTrace();}if(claims==null){filterChain.doFilter(request, response);return;}String usersubject = claims.getSubject();JSONObject entries = JSON.parseObject(usersubject);JSONArray authorities = entries.getJSONArray("authorities");String authlist="";for (int i = 0; i < authorities.size(); i++) {JSONObject o = (JSONObject) authorities.get(i);authlist=authlist+o.getString("authority")+",";}if(authlist.length()!=0){authlist = authlist.substring(0,authlist.length()-1);}User user = new User(entries.getString("username"), "", AuthorityUtils.commaSeparatedStringToAuthorityList(authlist));//存入SecurityContextHolderUsernamePasswordAuthenticationToken authenticationToken =new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());SecurityContextHolder.getContext().setAuthentication(authenticationToken);//放行filterChain.doFilter(request, response);}
}

好了,配置信息差不多就这些。

登录

登录的service:

public R login(SysUser tUser) {UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(tUser.getUsername(), tUser.getPassword());authenticate = authenticationManagerBean.authenticate(authenticationToken);if (Objects.isNull(authenticate)) {throw new RuntimeException("用户名或密码错误");}//获取用户信息User user = (User) authenticate.getPrincipal();//将用户信息存入jwtlog.info(user.toString());// hotool工具解析json少东西 更换为fastjsonString s1 = JSON.toJSONString(user);String jwt = JwtUtil.createJWT(s1,3600000L);//将jwt存入redisString token = UUID.randomUUID().toString().replaceAll("-","");redisCache.setCacheObject(token, jwt,3600000L);//把token响应给前端HashMap<String, String> map = new HashMap();map.put("token", token);return R.data(map);}

controller

import com.qian.chatgpt.util.R;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author gqs* @作者: Qiansheng* @创建时间:2023/4/23* @描述信息: TODO*/
@Slf4j
@RestController
@RequestMapping("/admin")
@CrossOrigin //关闭跨域验证
@Api(tags = "管理员管理")
public class AdminTestController {@PreAuthorize("hasAnyAuthority('admin:sel')")@ApiOperation(value = "管理员权限测试", notes = "管理员权限测试")@GetMapping("/test")public R test() {return R.success("admin权限测试成功");}
}

注意:@PreAuthorize(“hasAnyAuthority(‘admin:sel’)”) 中的admin:sel是权限

OK 结束!有什么问题评论或者留言都可以!

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

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

相关文章

基于 ThreadLocal 实现一个上下文管理组件(附源码)

点击关注公众号&#xff0c;Java干货及时送达&#x1f447; 本文基于ThreadLocal原理&#xff0c;实现了一个上下文状态管理组件Scope&#xff0c;通过开启一个自定义的Scope&#xff0c;在Scope范围内&#xff0c;可以通过Scope各个方法读写数据&#xff1b; 通过自定义线程池…

个人专属chatGpt免费使用,只需要2步

第一步&#xff1a;先下载Docker 下载网址&#xff1a;docker.com 选择自己合适的环境下载 安装&#xff1a; 等一丢丢会就可以了 我这里已经装过了&#xff0c;第一次装的话提示信息是&#xff1a;close and restart 需要重新下电脑 重启完电脑后就会自动跳出这个界面&#…

社群运营及新媒体运营常用工具清单列表,推荐收藏

做运营3年收集的运营人必备工具&#xff0c;推荐你收藏 每一个运营人都是积极向上且好学的&#xff0c;随着互联网的发展&#xff0c;作为一名运营要学习的东西也很多&#xff0c;除了要会文案外&#xff0c;美工设计的活有时也是你的&#xff0c;会脚本&#xff0c;会视频剪辑…

新媒体营销渠道大盘点

做新媒体营销一定要做的就是微信公众账号和微博&#xff0c;不管适合不适合&#xff0c;反正就是要做。其实有些时候未必都适合自己。所以选择适合自己的渠道才是最重要的。首先我们来看看都有哪些是新媒体营销的渠道。第一阵营微信公众账号和微博&#xff0c;相对于微信来说&a…

新媒体运营必备的实用工具

一、小葫芦 主要做和直播相关的数据分析&#xff0c;如 抖音、快手、 斗鱼、虎牙等主流直播平台 的收入榜、弹幕榜、 涨粉榜、 点赞榜、土豪榜&#xff0c;可以免费查询到的榜单数量比较多 对于一般用户够用了&#xff0c;另外小葫芦还提供一些和直播相关的小工具&#xff0c;…

品牌如何利用Instagram网红营销做好2023斋月推广?

在当今社交媒体的时代&#xff0c;Instagram已成为品牌进行营销和推广的重要平台之一&#xff0c;而且是最受穆斯林欢迎的社交媒体之一&#xff0c;超过60%的穆斯林用户会在Instagram上搜索和关注与斋月有关的话题和品牌。根据Instagram的数据&#xff0c;斋月期间&#xff0c;…

【独立站运营】用Facebook做社媒营销的关键点,你掌握了吗?

Facebook 是全球营销人员最常用的社交媒体平台。无论您的营销目标是什么&#xff0c;Facebook 都需要成为您战略的一部分。 不仅要学习如何创建 Facebook主页&#xff0c;还要学习如何有效地使用它来推广您的品牌&#xff0c;这一点至关重要。我们整理了设置和自定义专业 Face…

「品牌案例分享」-WhatsApp营销势成主流与更多用户交流互动

从电子邮件营销和付费广告到更传统的电视广告&#xff0c;企业有很多方法可以提高品牌知名度、获得新客户和让品牌壮大。然而&#xff0c;通过新颖和有创意的方式接触顾客才是挑战所在。 WhatsApp 是一种相当新的营销工具。由于WhatsApp 在全球拥有超过20 亿活跃用户&#xff0…

新闻个性化推荐系统

新闻个性化推荐系统 一、绪论及背景1.1、绪论1.2、背景1.3、发展历史 二、需求分析2.1、功能需求2.1.1、用户功能需求2.1.2、运营功能需求2.1.3、算法功能需求 2.2、非功能需求2.2.1、性能需求2.2.2、准确性需求2.2.3、稳定性需求2.2.4、可靠性需求 三、详细设计3.1、系统结构设…

【WhatsApp营销】如何将WhatsApp与品牌的社交媒体营销相结合

用多样的角色讲故事&#xff0c;设计吸引人的邮件&#xff0c;用令人惊叹的照片吸引眼球——营销人员已经全都做过。如今的社交媒体已经发展成为一个多面兽&#xff0c;各种形式和规模的营销策略和活动也随之出现&#xff0c;可以说营销人员已经尝试了各种可能的方式。 虽然说…

收藏级!运营人必备2021全年热点营销日历

一份热点全面的营销日历&#xff0c;可以帮我们更有效地制定年度营销计划、把握全年运营节奏。 以下就是小M制作的2021年度热点营销日历&#xff0c;包括通用节日节气、重大纪念日、互联网重要节日等上百个营销节点。 可以直接免费获取▼▼▼ 运营人必备&#xff01;2021热点…

App出海:如何制定社媒营销策略?

如今&#xff0c;国内互联网已进入存量时代&#xff0c;而海外市场一片蓝海&#xff0c;发展前景喜人&#xff0c;加上国内政策对出海的大力支持&#xff0c;出海成为了不少企业寻找增量的不二之选。根据Nox聚星&#xff08;NoxInfluencer&#xff09;调研数据&#xff0c;2022…

介绍几个主流社媒平台的特点,以及如何通过这些社媒渠道开展营销活动

介绍几个主流社媒平台的特点&#xff0c;以及如何通过这些社媒渠道开展营销活动 红人营销作为品牌营销的主要方式之一&#xff0c;它给品牌带来的流量转化是巨大的&#xff0c;之前的文章有讲述过红人的营销的主要操作是什么&#xff0c;也提到了每个社媒平台有自己的营销逻辑…

2023年适合营销公司使用的十大「社交媒体管理」工具

在遍地都是数字营销公司的时代&#xff0c;对品牌来说&#xff0c;拥有强大的社交媒体影响力以保持竞争力从未如此重要。 而对于管理一个或多个品牌的数字营销公司来说&#xff0c;从内容创作到执行报告&#xff0c;使用正确的工具可以帮助你做到这一点。从规划、管理和跟踪社…

ChatGPT 1.0.0安卓逆向分析,仅限中国分享

ChatGPT 1.0.0安卓逆向分析&#xff0c;仅限中国分享 本文将对ChatGpt Android版本1.0.0 APK进行静态解包分析和抓包分析&#xff0c;从ChatGpt Android APK功能的设计、校验过程和代码内包含的信息来预测OpenAI的大致走向。 Sensor Tower指出&#xff0c;在美国市场&#xff…

PC端微信网页打不开

首先&#xff0c;写这篇博客就是想吐槽一下。 我只是想看一片技术博文&#xff0c;手机上显示不太友好&#xff0c;有些代码没有超出边界被隐藏起来&#xff0c;想着在PC端应该更友好一些&#xff0c;结果在PC端打不开&#xff0c;不显示内容&#xff0c;然后浪费了一个下午的时…

无法打开网页但可以登录电脑微信 解决办法

今天遇到了电脑微信可以登录但网页打不开的情况&#xff0c;原因可能是DNS 配置出现问题。DNS&#xff08;Domain Name System&#xff0c;域名系统&#xff09;可以简单的理解成根据域名解析成对应IP的解码服务器。 解决办法 1. 打开控制面板 2. 选择网络和Internet - 网络和…

解决网络连接正常,网页打不开的问题

win10系统 1.打开‘控制面板-’->点击‘网络和Internet’ 2.点击‘Internet 选项’ 3.在弹出的‘Internet’属性窗口选择上方的‘连接’选项栏-->点击下方的‘局域网设置’ 4.在弹出的‘局域网&#xff08;LAN&#xff09;设置’窗口的‘代理服务器’部分&#xff0c;取…

网站浏览器可以打开,在微信中打不开,排查问题的过程

今天收到遇到一个诡异的问题&#xff1a;网站浏览器可以打开&#xff0c;在微信中打不开&#xff0c;耗费了很长时间才将问题排查出来&#xff0c;现在将排查的步骤记录下来&#xff0c;仅供参考&#xff1a; 在手机微信里输入访问地址&#xff1a;显示无法 打开网页。如图所示…

关于网络很快 但是打不开腾讯相关网页的解决办法 亲测有效!

刷新见效果 刷新见效果 刷新见效果 重要的事情要提三遍 近日 发现我的电脑打不开电脑版微信里面的网页内容&#xff0c;进而发现连腾讯的微信公众号的主页也打不开&#xff0c;经过网上的查询和大量的尝试&#xff0c;终于发现解决办法&#xff0c;立竿见影&#xff1a; 打…