OddFar's Notes OddFar's Notes
首页
  • Java-Se

    • Java基础
    • Java面向对象
    • Java常用类
    • Java集合框架
  • Java-Se进阶

    • JUC多线程
  • Java-ee

    • JavaWeb
  • SQL 数据库

    • MySQL
  • NoSQL 数据库

    • Redis
    • ElasticSearch
    • MongoDB
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • Spring

    • Spring
  • 中间件

    • RabbitMQ
  • Git
  • Docker
  • Jenkins
  • 校园信息墙
关于
归档
GitHub (opens new window)
首页
  • Java-Se

    • Java基础
    • Java面向对象
    • Java常用类
    • Java集合框架
  • Java-Se进阶

    • JUC多线程
  • Java-ee

    • JavaWeb
  • SQL 数据库

    • MySQL
  • NoSQL 数据库

    • Redis
    • ElasticSearch
    • MongoDB
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • Spring

    • Spring
  • 中间件

    • RabbitMQ
  • Git
  • Docker
  • Jenkins
  • 校园信息墙
关于
归档
GitHub (opens new window)
  • 校园信息墙

    • Campus - 目录页
    • 项目简介
    • 项目启动
    • 权限控制
      • 认证方式
      • 权限结构
      • 拓展介绍
        • JWT介绍
        • 自己实现登录功能
        • 拦截器使用方法
        • 盐值加密
      • 参考资料
  • 项目
  • 校园信息墙
zhiyuan
2022-03-03
目录

权限控制

# 认证方式

采用 jwt token方式 进行认证,每次请求时附带 token 代表自己的身份标识,用来”认识“用户

jwt缺点是不能及时销毁,可配上 redis 进行二次验证,也方便拓展,例如:查看登录用户,踢下线用户

提示

使用 SpringScurity 工具进行验证

一开始只是自己实现登录功能,再配合 拦截器,对所需的URL进行验证,token验证成功则通过

好处就是使用简单,但适合简单的业务,高拓展性推荐用 SpringScurity

# 权限结构

目前就三个角色:普通用户、管理员、系统管理员

使用到三个表:sys_user、role、user_role

在 sys_user 表中用字段 user_type 区分用户类型

角色固定情况下,只需一个表,用字段判断即可,后续可能加入自定义角色,所以我就用了三个表来区分权限

授权过程(大部分功能采用若依代码)

1、登录密码验证:SysUserServiceImpl.loadUserByUsername()

​ 登录用到的userName实则是用户的账号userAccount

2、登录成功:AuthenticationFilter.successfulAuthentication()

3、创建token,把用户的登录信息存入redis,key为随机的UUID:tokenService.createToken

每次URL请求验证token正确性在:MyAuthenticationFilter

token的秘钥和有效时间可在 application.yml修改

待完善功能

  • 修改用户信息时,redis数据没同步过去
  • 更改用户状态时,不会把用户踢下线
  • 查看在线用户(懒得 ctrl v 若依代码)

# 拓展介绍

# JWT介绍

JWT(Json Web Token)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。

JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。比如用在用户登录上

JWT最重要的作用就是对 token信息的防伪作用。

一个JWT由三个部分组成:公共部分、私有部分、签名部分。最后由这三者组合进行base64编码得到JWT。

image-20211012102155624

1、 公共部分

主要是该JWT的相关配置参数,比如签名的加密算法、格式类型、过期时间等等。

2、 私有部分

用户自定义的内容,根据实际需要真正要封装的信息。

userInfo{用户的Id,用户的昵称}

3、 签名部分

SaltiP: 当前服务器的Ip地址{linux 中配置代理服务器的ip}

主要用户对JWT生成字符串的时候,进行加密{盐值}

最终组成 key+salt+userInfo = token

base64编码,并不是加密,只是把明文信息变成了不可见的字符串。其实只要用一些工具就可以把base64编码解成明文,所以不要在JWT中放入涉及私密的信息。

# 自己实现登录功能

要引入security依赖

  • 注册时 BCrypt 加密密码:
public String BCrypt(String password) {
    BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    //加密后新密码
    String newPassword = passwordEncoder.encode(password);
    return newPassword;
}
1
2
3
4
5
6
  • 密码比较,正确返回true
//密码比较
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
boolean matches = passwordEncoder.matches(password, userInfo.getPassword());
1
2
3

判断密码,正确生成token并返回,之后再用拦截器,对需要验证的URL判断token是否为管理员

# 拦截器使用方法

一开始采用拦截器,对相应的每次URL请求来验证 token

用法如下

  • 1、添加拦截器配置
@Configuration
public class MyWebConfig implements WebMvcConfigurer {

    @Bean
    UserInterceptor userInterceptor() {
        return new UserInterceptor();
    }

    @Bean
    AdminInterceptor adminInterceptor() {
        return new AdminInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(new AdminInterceptor()).addPathPatterns("/admin/**");
        registry.addInterceptor(adminInterceptor()).addPathPatterns("/admin/**");
        // 拦截器里需要使用到 @Autowired 需要Bean注入
        // 没用到直接 new AdminInterceptor() 即可

        WebMvcConfigurer.super.addInterceptors(registry);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  • 实现拦截器方法
//具体拦截器的业务类
public class AdminInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    //在请求处理之前进行调用: Controller方法调用之前
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {

        String token = request.getHeader("X-Token");
       	/**
       	下面为判断token是否有效
       	有效返回:true
       	失效则不通过:false
       	**/
	
        }
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
//        System.out.println("postHandle被调用");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
//        System.out.println("afterCompletion被调用");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 盐值加密

在用户模块,对于用户密码的保护,通常都会进行加密。我们通常对密码进行加密,然后存放在数据库中,在用户进行登录的时候,将其输入的密码进行加密然后与数据库中存放的密文进行比较,以验证用户密码是否正确。

目前,MD5和BCrypt比较流行。相对来说,BCrypt比MD5更安全,但加密更慢。

加盐

如果两个人或多个人的密码相同,加密后保存会得到相同的结果。破一个就可以破一片的密码。如果名为A的用户可以查看数据库,那么他可以观察到自己的密码和别人的密码加密后的结果都是一样,那么,别人用的和自己就是同一个密码,这样,就可以利用别人的身份登录了。

其实只要稍微混淆一下就能防范住了,这在加密术语中称为“加盐”。具体来说就是在原有材料(用户自定义密码)中加入其它成分(一般是用户自有且不变的因素),以此来增加系统复杂度。当这种盐和用户密码相结合后,再通过摘要处理,就能得到隐蔽性更强的摘要值。

# 参考资料

  • 若依项目部分代码

  • SpringBoot实现Vue-admin-template登录

    https://www.cnblogs.com/codeluojay/p/13123494.html

  • vue+springboot实现登录验证码(前后端分离)

    https://blog.csdn.net/pp1981002445/article/details/110954646

  • 基于token的springsecurity前后端分离实现

    https://blog.csdn.net/weixin_42375707/article/details/113247664

  • springboot学习(二十二)_ 使用@Constraint注解自定义验证注解 (opens new window)

  • https://www.bilibili.com/video/BV1mm4y1X7Hc

在 GitHub 上编辑此页 (opens new window)
最后更新: 2022/08/07, 3:08:00
项目启动

← 项目启动

最近更新
01
ES - 分词
07-28
02
ES - 索引管理
07-28
03
项目启动
03-03
更多文章>
Theme by Vdoing | Copyright © 2021-2022 oddfar | 冀ICP备20001094号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式