鉴权.2

简介: 本文介绍如何在Spring Boot中集成Spring Security与JWT实现认证授权。通过自定义UserDetailsService、JWT过滤器及权限配置,完成登录生成Token、请求验证等流程,并结合RBAC模型实现细粒度访问控制。

2.7 接口类

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDTO getUserByIdCardNo(String idCardNo) {
        return userMapper.getUserByIdCardNo(idCardNo);
    }
}
@Repository
public interface UserMapper {

    /**
     * 查找患者信息
     * @param idCardNo
     * @return
     */
    UserDTO getUserByIdCardNo(String idCardNo);
}
<select id="getUserByIdCardNo" parameterType="String" resultMap="userEntity">
  SELECT * FROM USER
  <where>
    <if test="idCardNo != null">
      ID_CARD_NO =#{idCardNo}
    </if>
    AND VALID_FLAG='ENABLE'
  </where>
  LIMIT 1
</select>

下面实现JWTLoginFilter 这个Filter比较简单,除了构造函数需要重写三个方法。

  • attemptAuthentication - 登录时需要验证时候调用
  • successfulAuthentication - 验证成功后调用
  • unsuccessfulAuthentication - 验证失败后调用,这里直接灌入500错误返回,由于同一JSON返回,HTTP就都返回200了


2.8 JWTLoginFilter

import com.fasterxml.jackson.databind.ObjectMapper;
import com.test.framework.client.dto.response.JSONResultDTO;
import com.test.framework.web.domain.vo.AccountCredentials;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
    public JWTLoginFilter(String url, AuthenticationManager authManager) {
        super(new AntPathRequestMatcher(url));
        setAuthenticationManager(authManager);
    }
    @Override
    public Authentication attemptAuthentication(
            HttpServletRequest req, HttpServletResponse res)
            throws AuthenticationException, IOException, ServletException {
        // JSON反序列化成 AccountCredentials
        AccountCredentials creds = new ObjectMapper().readValue(req.getInputStream(), AccountCredentials.class);
        // 返回一个验证令牌
        return getAuthenticationManager().authenticate(
                new UsernamePasswordAuthenticationToken(
                        creds.getUsername(),
                        creds.getPassword()
                )
        );
    }
    @Override
    protected void successfulAuthentication(
            HttpServletRequest req,
            HttpServletResponse res, FilterChain chain,
            Authentication auth) throws IOException, ServletException {
        TokenAuthenticationService.addAuthentication(res, auth.getName());
    }
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        response.setContentType("application/json");
        response.setStatus(HttpServletResponse.SC_OK);
        response.getOutputStream().println(JSONResult.fillResultString(500, "Internal Server Error!!!", JSONObject.NULL));
    }
}

再完成最后一个类JWTAuthenticationFilter,这也是个拦截器,它拦截所有需要JWT的请求,然后调用TokenAuthenticationService类的静态方法去做JWT验证。

2.9 拦截器JWTAuthenticationFilter

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

class JWTAuthenticationFilter extends GenericFilterBean {
    @Override
    public void doFilter(ServletRequest request,
                         ServletResponse response,
                         FilterChain filterChain)
            throws IOException, ServletException {
        Authentication authentication = TokenAuthenticationService
                .getAuthentication((HttpServletRequest)request);
        SecurityContextHolder.getContext()
                .setAuthentication(authentication);
        filterChain.doFilter(request,response);
    }
}

现在代码就写完了,整个Spring Security结合JWT基本就差不多了,下面我们来测试下,并说下整体流程。

开始测试,先运行整个项目,这里介绍下过程:

  • 先程序启动 - main函数
  • 注册验证组件 - WebSecurityConfigconfigure(AuthenticationManagerBuilder auth)方法,这里我们注册了自定义验证组件
  • 设置验证规则 - WebSecurityConfigconfigure(HttpSecurity http)方法,这里设置了各种路由访问规则
  • 初始化过滤组件 - JWTLoginFilterJWTAuthenticationFilter 类会初始化

首先测试获取Token,这里使用CURL命令行工具来测试。

2.10 验证

curl -H "Content-Type: application/json" -X POST -d '{"username":"admin","password":"123456"}' http://127.0.0.1:8080/login
{
  "result": "eyJhbGciOiJIUzUxMiJ9.eyJhdXRob3JpdGllcyI6IlJPTEVfQURNSU4sQVVUSF9XUklURSIsInN1YiI6ImFkbWluIiwiZXhwIjoxNDkzNzgyMjQwfQ.HNfV1CU2CdAnBTH682C5-KOfr2P71xr9PYLaLpDVhOw8KWWSJ0lBo0BCq4LoNwsK_Y3-W3avgbJb0jW9FNYDRQ",
  "message": "",
  "status": 0
}

这里我们得到了相关的JWT,反Base64之后,就是下面的内容,标准JWT

{"alg":"HS512"}{"authorities":"ROLE_ADMIN,AUTH_WRITE","sub":"admin","exp":1493782240}ͽ]BS`pS6~hCVH%
ܬ)֝ଖoE5р

整个过程如下:

  • 拿到传入JSON,解析用户名密码 - JWTLoginFilterattemptAuthentication 方法
  • 自定义身份认证验证组件,进行身份认证 - CustomAuthenticationProviderauthenticate 方法
  • 盐城成功 - JWTLoginFiltersuccessfulAuthentication 方法
  • 生成JWT - TokenAuthenticationServiceaddAuthentication方法


再测试一个访问资源的:

curl -H "Content-Type: application/json" -H "Authorization: Bearer eyJhbGciOiJIUzUxMiJ9.eyJhdXRob3JpdGllcyI6IlJPTEVfQURNSU4sQVVUSF9XUklURSIsInN1YiI6ImFkbWluIiwiZXhwIjoxNDkzNzgyMjQwfQ.HNfV1CU2CdAnBTH682C5-KOfr2P71xr9PYLaLpDVhOw8KWWSJ0lBo0BCq4LoNwsK_Y3-W3avgbJb0jW9FNYDRQ"http://127.0.0.1:8080/users

结果:

{
  "result":["freewolf","tom","jerry"],
  "message":"",
  "status":0
}

说明我们的Token生效可以正常访问。其他的结果您可以自己去测试。再回到处理流程:
接到请求进行拦截 - JWTAuthenticationFilter 中的方法
验证JWT - TokenAuthenticationService 类 getAuthentication 方法
访问Controller
这样本文的主要流程就结束了,本文主要介绍了,如何用Spring Security结合JWT保护你的Spring Boot应用。如何使用Role和Authority,这里多说一句其实在Spring Security中,对于GrantedAuthority接口实现类来说是不区分是Role还是Authority,二者区别就是如果是hasAuthority判断,就是判断整个字符串,判断hasRole时,系统自动加上ROLE_到判断的Role字符串上,也就是说hasRole("CREATE")和hasAuthority('ROLE_CREATE')是相同的。利用这些可以搭建完整的RBAC体系。本文到此,你已经会用了本文介绍的知识点。


目录
相关文章
|
1天前
|
数据采集 人工智能 安全
|
10天前
|
云安全 监控 安全
|
2天前
|
自然语言处理 API
万相 Wan2.6 全新升级发布!人人都能当导演的时代来了
通义万相2.6全新升级,支持文生图、图生视频、文生视频,打造电影级创作体验。智能分镜、角色扮演、音画同步,让创意一键成片,大众也能轻松制作高质量短视频。
902 150
|
15天前
|
机器学习/深度学习 人工智能 自然语言处理
Z-Image:冲击体验上限的下一代图像生成模型
通义实验室推出全新文生图模型Z-Image,以6B参数实现“快、稳、轻、准”突破。Turbo版本仅需8步亚秒级生成,支持16GB显存设备,中英双语理解与文字渲染尤为出色,真实感和美学表现媲美国际顶尖模型,被誉为“最值得关注的开源生图模型之一”。
1640 8
|
6天前
|
人工智能 前端开发 文件存储
星哥带你玩飞牛NAS-12:开源笔记的进化之路,效率玩家的新选择
星哥带你玩转飞牛NAS,部署开源笔记TriliumNext!支持树状知识库、多端同步、AI摘要与代码高亮,数据自主可控,打造个人“第二大脑”。高效玩家的新选择,轻松搭建专属知识管理体系。
362 152
|
7天前
|
人工智能 自然语言处理 API
一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸
一句话生成拓扑图!next-ai-draw-io 结合 AI 与 Draw.io,通过自然语言秒出架构图,支持私有部署、免费大模型接口,彻底解放生产力,绘图效率直接爆炸。
600 152
|
9天前
|
人工智能 安全 前端开发
AgentScope Java v1.0 发布,让 Java 开发者轻松构建企业级 Agentic 应用
AgentScope 重磅发布 Java 版本,拥抱企业开发主流技术栈。
561 13
|
2天前
|
编解码 人工智能 机器人
通义万相2.6,模型使用指南
智能分镜 | 多镜头叙事 | 支持15秒视频生成 | 高品质声音生成 | 多人稳定对话