Spring Security实现登陆认证授权

您所在的位置:网站首页 configure失败 Spring Security实现登陆认证授权

Spring Security实现登陆认证授权

2023-04-19 08:33| 来源: 网络整理| 查看: 265

前端可以根据权限信息控制菜单和页面展示,操作按钮的显示。但这并不够,如果有人拿到了接口,绕过了页面直接操作数据,这是很危险的。所以我们需要在后端也加入权限控制,只有拥有操作权限,该接口才能被授权访问。 在进入Controller方法前判断当前用户是否拥有访问权限,可以通过Filter加AOP的方式实现认证和授权。本次介绍的是成熟的框架:Spring Security。其他框架还有Shiro等。

前端可以根据权限信息控制菜单和页面展示,操作按钮的显示。但这并不够,如果有人拿到了接口,绕过了页面直接操作数据,这是很危险的。所以我们需要在后端也加入权限控制,只有拥有操作权限,该接口才能被授权访问。

在进入Controller方法前判断当前用户是否拥有访问权限,可以通过Filter加AOP的方式实现认证和授权。本次介绍的是成熟的框架:Spring Security。其他框架还有Shiro等。

Spring Security简介

Spring Security的重要核心功能功能是“认证”和“授权”,即用户认证(Authentication)和用户授权(Authorization)两部分:

(1)用户认证指的是:验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求提供用户名和密码,系统通过校验用户名和密码来完成认证过程。

(2)用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,用的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。

Spring Security的特点:

和Spring无缝整合 全面的权限控制 专门为Web开发而设计 重量级

Spring Boot出现后,其为Spring Security提供了自动配置方案,可以使用少量的配置来使用Spring Security。如果你的项目是基于Spring Boot的,使用Spring Security无疑是很棒的选择!

Spring Security实现权限

要对Web资源进行保护,最好的办法莫过于Filter

要对方法调用进行保护,最好的方法莫过于AOP

Spring Security进行认证和鉴权的时候就是利用一系列的Filter进行拦截的。

如图所示,一个请求要想访问到API就会从左到右经过蓝线框里的过滤器,其中绿色部分是负责认证的过滤器,蓝色部分就是负责异常处理,橙色部分则是负责授权。经过一系列拦截最终访问到我们的API。

FilterSecurityInterceptor:是一个方法级的过滤器,基本位于过滤链的最底部。 ExceptionTranslationFilter:是一个异常过滤器,用来处理在认证授权过程中抛出的异常。 UsernamePasswordAuthenticationFilter:对/login的POST请求做拦截,校验表单中用户名、密码。

这里我们只需要重点关注两个过滤器即可:UsernamePasswordAuthenticationFilter负责登陆认证,FilterSecurityInterceptor负责权限授权。

说明:Spring Security的核心逻辑全在这一套过滤器中,过滤器里会调用各种组件完成功能,掌握了这些过滤器和组件你就掌握了Spring Security!这个框架的使用方式就是对这些过滤器和组件进行扩展。

用户认证流程

自定义组件

根据认证流程,我们需要自定义以下组件:

UserDetails loadUserByUsername passwordEncoder

1、登陆Filter,判断用户名和密码是否正确,生成token

2、认证解析token组件,判断请求头是否有token,如果有认证完成

3、在配置类配置相关认证类

代码实现

完整项目地址:Server | GitHub

依赖

创建一个spring-security模块(module),可以放在项目的common模块下

创建完成,导入相关的Maven依赖

org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-web provided 工具类 ResponseUtil

用于写会数据给前端

import com.fasterxml.jackson.databind.ObjectMapper; import com.swx.common.pojo.R; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class ResponseUtil { public static void out(HttpServletResponse response, R r) { ObjectMapper mapper = new ObjectMapper(); response.setStatus(HttpStatus.OK.value()); response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setCharacterEncoding("UTF-8"); try { mapper.writeValue(response.getWriter(), r); } catch (IOException e) { throw new RuntimeException(e); } } } JwtHelper package com.swx.common.jwt; import io.jsonwebtoken.*; import org.springframework.util.StringUtils; import java.util.Date; public class JwtHelper { private static long tokenExpiration = 60 * 60 * 1000; private static String tokenSignKey = "xxxxxx"; public static String createToken(Long userId, String username) { return Jwts.builder() .setSubject("AUTH-USER") .setExpiration(new Date(System.currentTimeMillis() + tokenExpiration)) .claim("userId", userId) .claim("username", username) .signWith(SignatureAlgorithm.HS512, tokenSignKey) .compressWith(CompressionCodecs.GZIP) .compact(); } public static Long getUserId(String token) { try { if (StringUtils.isEmpty(token)) return null; Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); Claims body = claimsJws.getBody(); String userId = body.get("userId").toString(); return Long.parseLong(userId); } catch (Exception e) { e.printStackTrace(); return null; } } public static String getUsername(String token) { try { if (StringUtils.isEmpty(token)) return null; Jws claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token); Claims body = claimsJws.getBody(); return (String) body.get("username"); } catch (Exception e) { e.printStackTrace(); return null; } } } 自定义UserDetail

继承UserDetail的User,其中sysUser是项目数据库的实体类

import com.swx.model.system.SysUser; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.User; import java.util.Collection; public class CustomUser extends User { private SysUser sysUser; public CustomUser(SysUser sysUser, Collection


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3