96SEO 2026-02-20 09:00 20
SpringSecurity】认证授权框架——SpringSecurity使用方法

文章目录【SpringSecurity】认证授权框架——SpringSecurity使用方法1.
认证au***ntication、授权authorization和保护以抵御常见的攻击。
它对保护命令式和响应式应用程序有一流的支持是保护基于Spring的应用程序的事实标准。
它还提供了与其他库的集成以简化其使用。
写这篇文章主要是为了复习SpringSecurity的相关知识在这里也向大家推荐b站up主
parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.5.0/version
dependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependency!--主要是这个依赖--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-security/artifactId/dependency
引入好依赖之后就可以启动应用了我们访问应用的任何一个接口都会跳转到SpringSecurity的一个默认登录页面(如下所示)
使用默认的用户名和控制台上的密码就能够登录系统访问接口了。
在正常情况下我们需要禁用这个接口使用我们自定义的接口。
我们主要了解第一种方式。
SpringSecurity认证通过过滤器链实现
SpringSecurity的过滤器链包含15个过滤器上图只展示了较为核心的过滤器。
SecurityContextPersistenceFilter过滤器链的入口和出口保存和清除
。
UsernamePasswordAu***nticationFilter负责收集我们在登陆页面输入的用户名和密码并封装成Au***ntication对象。
ExceptionTranslationFilter只处理过滤器链中抛出的任何AccessDeniedException和Au***nticationException
其他异常继续抛出。
FilterSecurityInterceptor负责权限校验的过滤器。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ailkTJHA-1680426554649)(null)]
Au***ntication是一个接口它的实现类表示当前访问系统的用户封装了用户相关信息。
Au***nticationManager也是一个接口声明了认证Au***ntication的方法UserDetailsService还是一个接口加载用户特定数据的核心接口。
里面定义了一个根据用户名查询用户信息的方法。
UserDetails接口提供核心用户信息。
通过UserDetailsService根据用户名获取处理的用户信息要封装成UserDetails对象返回。
然后将这些信息封装到Au***ntication对象中。
自定义实现UserDetailService接口的类A替代原有实现类。
校验通过则使用jwt工具类生成tokentoken生成规则有两种
使用用户基本信息的json串(脱敏)生成token服务端不必存储用户信息。
解析获得用户id根据用户id从redis中获得用户信息存入SecurityContextHolder。
解析获得用户信息json串将其反序列化为用户对象存入SecurityContextHolder。
创建UserDetailsService接口的实现类在其中对用户进行认证和授权。
LambdaQueryWrapper();queryWrapper.eq(StringUtils.isNotBlank(username),
userMapper.selectOne(queryWrapper);if
RuntimeException(用户名或密码错误);}//todo
查询对应的权限信息//把数据封装成UserDetails返回UserDetails
org.springframework.security.core.userdetails.User.withUsername(user.getUserName()).password(user.getPassword()).authorities(new
}除了使用security提供的生成UserDetails对象的方法外我们还可以选择自定义。
user.getPassword();}Overridepublic
user.getUserName();}Overridepublic
LambdaQueryWrapper();queryWrapper.eq(StringUtils.isNotBlank(username),
userMapper.selectOne(queryWrapper);if
RuntimeException(用户名或密码错误);}//todo
查询对应的权限信息//把数据封装成UserDetails返回return
我们不会在数据库中使用明文的方式存储密码我们需要存储的是加密之后的密码。
SpringSecurity默认使用的PasswordEncoder要求数据库中的密码格式为{id}password
。
它会根据id去判断密码的加密方式。
这种方式不太行所以我们需要使用BCryptPasswordEncoder去替代原来的PasswordEncoder。
我们只需要定义一个SpringSecurity的配置类并且让这个类继承
userService;PostMapping(/user/login)public
我们需要让SpringSecurity对自定义的接口放行让用户不用登陆也可以访问。
然后在
中调用Au***nticationManager的au***nticate方法来进行用户认证所以需要在SpringSecurity配置类中进行以下两点配置
BCryptPasswordEncoder();}//注入Au***nticationManager对象OverrideBeanpublic
super.au***nticationManagerBean();}//对登录接口放行Overrideprotected
{http//关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()//
允许匿名访问(未登录时可以访问登陆后不能访问).antMatchers(/user/login).anonymous()//
除上面外的所有请求全部需要鉴权认证.anyRequest().au***nticated();}
stringRedisTemplate;Autowiredprivate
au***nticationManager;Overridepublic
方法进行用户认证UsernamePasswordAu***nticationToken
UsernamePasswordAu***nticationToken(user.getUserName(),
user.getPassword());Au***ntication
au***nticationManager.au***nticate(au***nticationToken);}
RuntimeException(e.getMessage());}if
RuntimeException(登陆失败);}//如果认证未通过则给出对应提示//通过则使用userid生成一个jwtjwt存入ResponseResultLoginUser
au***nticate.getPrincipal();String
loginUser.getUser().getId().toString();String
JwtUtil.createJWT(userId);MapString,
jwt);//把用户信息存入redisstringRedisTemplate.opsForValue().set(login:
JSON.toJSONString(loginUser));return
stringRedisTemplate;Overrideprotected
doFilterInternal(HttpServletRequest
{//没有token//放行让后面的认证过滤器去拒绝filterChain.doFilter(request,
response);return;}//解析tokenString
RuntimeException(token非法);}//拼接redis的keyString
stringRedisTemplate.opsForValue().get(key);if
(StringUtils.isBlank(userJson))
RuntimeException(用户未登录);}LoginUser
LoginUser.class);//存入SecurityContextHolder//todo
还未授权UsernamePasswordAu***nticationToken
UsernamePasswordAu***nticationToken(loginUser,
null);SecurityContextHolder.getContext().setAu***ntication(au***nticationToken);//放行filterChain.doFilter(request,
定义了认证过滤器后我们还需要确定过滤器的执行顺序我们必须保证这个过滤器的执行在Security的认证过滤器之前所以我们把他放在
UsernamePasswordAu***nticationFilter
jwtAu***nticactionTokenFilter;protected
{http//关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()//
允许匿名访问(未登录时可以访问登陆后不能访问).antMatchers(/user/login).anonymous()//
除上面外的所有请求全部需要鉴权认证.anyRequest().au***nticated();//把自定义认证过滤器放在
UsernamePasswordAu***nticationFilter
过滤波器前面http.addFilterBefore(jwtAu***nticactionTokenFilter,
UsernamePasswordAu***nticationFilter.class);
获得用户id利用用户id凭借redis的key值通过key值把redis中的用户信息删除
{//获取SecurityContextHolder中的用户idAu***ntication
SecurityContextHolder.getContext().getAu***ntication();LoginUser
au***ntication.getPrincipal();Long
loginUser.getUser().getId();//删除redis中的值stringRedisTemplate.delete(login:
在SpringSecurity中会使用默认的FilterSecurityInterceptor来进行权限校验。
在FilterSecurityInterceptor中会从SecurityContextHolder获取其中的Au***ntication然后获取其中的权限信息。
当前用户是否拥有访问当前资源所需的权限。
EnableGlobalMethodSecurity(prePostEnabled
PreAuthorize(hasAuthority(test))
权限的封装是在登录流程时发生的所以我们在登录方法中把权限信息封装进入
permissions;//权限集合,不用序列化到redisJSONField(serialize
permissions;}//将权限字符串集合封装成权限集合Overridepublic
SimpleGrantedAuthority(item)).collect(Collectors.toSet());}return
user.getPassword();}Overridepublic
user.getUserName();}Overridepublic
LambdaQueryWrapper();queryWrapper.eq(StringUtils.isNotBlank(username),
userMapper.selectOne(queryWrapper);if
RuntimeException(用户名或密码错误!);}//查询对应的权限信息ListString
menuMapper.selectPermsByUserId(user.getId());return
UsernamePasswordAu***nticationToken
UsernamePasswordAu***nticationToken(loginUser,
loginUser.getAuthorities());4.3
Security提供的权限校验方法比较单一且不灵活。
所以我们可以自定义权限校验方法并且在注解中使用我们的方法。
SecurityContextHolder.getContext().getAu***ntication();LoginUser
au***ntication.getPrincipal();ListString
loginUser.getPermissions();//判断用户是否拥有访问权限return
permissions.contains(authority);}
//PreAuthorize(hasAuthority(system:dept:list))
PreAuthorize(ex.hasAuthority(system:dept:list))
我们上面的示例都是基于注解的权限控制我们也可以通过配置来进行权限的控制如下所示
允许匿名访问.antMatchers(/user/login).anonymous()//基于配置的权限控制.antMatchers(/testCors).hasAuthority(system:dept:list222)//
除上面外的所有请求全部需要鉴权认证.anyRequest().au***nticated();5.
我们还希望在认证失败或者是授权失败的情况下也能和我们的接口一样返回相同结构的json这样可以让前端能对响应进行统一的处理。
要实现这个功能我们需要知道SpringSecurity的异常处理机制。
在SpringSecurity中如果我们在认证或者授权的过程中出现了异常会被ExceptionTranslationFilter捕获到。
在ExceptionTranslationFilter中会去判断是认证失败还是授权失败出现的异常。
如果是认证过程中出现的异常会被封装成Au***nticationException然后调用Au***nticationEntryPoint对象的方法去进行异常处理。
如果是授权过程中出现的异常会被封装成AccessDeniedException然后调用AccessDeniedHandler对象的方法去进行异常处理。
所以如果我们需要自定义异常处理我们只需要自定义Au***nticationEntryPoint和AccessDeniedHandler然后配置给SpringSecurity即可。
ResponseResult(HttpStatus.UNAUTHORIZED.value(),
JSON.toJSONString(result);//处理异常WebUtils.renderString(httpServletResponse,
renderString(HttpServletResponse
{try{response.setStatus(200);response.setContentType(application/json);response.setCharacterEncoding(utf-8);response.getWriter().print(string);}catch
ResponseResult(HttpStatus.FORBIDDEN.value(),
JSON.toJSONString(result);//处理异常WebUtils.renderString(httpServletResponse,
au***nticationEntryPoint;Autowired
{//省略其他配置......//配置异常处理器http.exceptionHandling().au***nticationEntryPoint(au***nticationEntryPoint)//认证失败处理器.accessDeniedHandler(accessDeniedHandler);//授权失败处理器
只有浏览器和服务端的之间的请求有跨域问题服务端和服务端之间是不存在跨域问题的。
设置允许跨域的路径registry.addMapping(/**)//
设置允许跨域请求的域名.allowedOriginPatterns(*)//
是否允许cookie.allowCredentials(true)//
设置允许的header属性.allowedHeaders(*)//
}由于我们的资源都会收到SpringSecurity的保护所以想要跨域访问还要让SpringSecurity运行跨域访问。
{//省略其他配置......//允许跨域http.cors();
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback