后端登录安全的一种思路

PS:作者是小白能接触到的就只会这样写。勿喷。

前提

思路: 结合io流将登录token存储到配置文件中,不将token存储到浏览器端,从而避免盗取。

下面jwt的学习可以参考下这个:

JWT --- 入门学习_本郡主是喵的博客-CSDN博客

JWT工具类

java 复制代码
@Component
public class JWTtUtils {

    public static final String USER_NAME = "username";
    public static final String PASS_WORD = "password";
    public static final String CREATE_TIME = "createTime";
    public static final String SIGN_KEY = "QHX2004"; // 解析key
    /**
     * 用用户名和密码生成JWT
     *
     * @param username
     * @param password
     * @return
     */

    public String generatorJWTFromUserNameAndPassword(String username,String password){
        HashMap<String, Object> hashMap = new HashMap<>(); // 生成map
        hashMap.put(USER_NAME,username);
        hashMap.put(PASS_WORD,password);
        hashMap.put(CREATE_TIME,new Date());
        return  generatorJWTFromUserNameAndPassword(hashMap);
    }

    /**
     * 生成jwt过期时间,1个月
     *
     * @param
     * @return
     */
    private Date generatorExpirationDate() {
        return new Date(System.currentTimeMillis() + (1000L * 60 * 60 *24 *30));
    }

    /**
     * 用用户名和密码生成jwt
     *
     * @param paramMap
     * @return
     */
    private String generatorJWTFromUserNameAndPassword(HashMap<String, Object> paramMap) {
        JwtBuilder jwtBuilder = Jwts.builder()
                .setClaims(paramMap)
                .setExpiration(generatorExpirationDate()) // 设置过期时间
                .signWith(SignatureAlgorithm.HS512,SIGN_KEY);
        return jwtBuilder.compact(); // 拿到token
    }



    /**
     * 解析token拿到Claims
     *
     *
     * @param token
     * @return
     */
     private Claims getClaimsFromToken(String token){
        Claims claims = Jwts.parser()
                .setSigningKey(SIGN_KEY)
                .parseClaimsJws(token)
                .getBody();

        return claims;
    }

    /**
     * 校验token是否过期
     *
     * @param token
     * @return
     */
  // 过期返回true
    public boolean checkTokenIsOverdue(String token){
        Claims claims = getClaimsFromToken(token);
        Date date =  claims.getExpiration();
        return date.getTime() < new Date().getTime();
    }


    /**
     * 刷新token:重新生成一个token
     *
     * @param
     * @return
     */

    public String flushToken(String token){
        Claims claims = getClaimsFromToken(token);
        String username = (String) claims.get(USER_NAME);
        String password = (String)claims.get(PASS_WORD);
        return generatorJWTFromUserNameAndPassword(username,password);
    }

}

IO工具类

java 复制代码
public class IOUtils {


    public static final String FILE_NAME = "conf.properties";

    /**
     *   配置文件读取
     * @param key
     * @return  value
     */

    public static String getPropertiesKey(String key)  {
      return  getKey(key);
    }

    /**
     * 配置文件读取
     *
     * @param  key
     * @return
     */
    private static String getKey(String key) {
        Properties properties = new Properties();
        File file = new File(FILE_NAME);
        FileInputStream inputStream = null;
        try {
            inputStream = new FileInputStream(file);
            properties.load(inputStream); // 其实已经将配置文件拿到手了
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(inputStream != null){  // 还是这样关比较好,万一报错就tm关不了
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return  properties.getProperty(key);
    }

    /**
     * 配置文件设置
     *
     * @param key
     * @param value
     * @return
     */
    public static boolean setPropertiesKey(String key,String value) {
        // 判断key是否有重复
        String key1 = getKey(key);
        if(key1 == null){
            return setKey(key,value); // 把核心业务逻辑抽出来
        }
        return false;
    }

    /**
     *  配置文件设置
     *
     * @param key
     * @param value
     * @return boolean
     */
    private static boolean setKey(String key, String value) {
        Properties properties = new Properties();
        File file = new File(FILE_NAME); // 其实有其他配置可以同意下yaml文件里面配置,然后这里面读取,好统一调配。
        FileWriter fileWriter = null;
        try {
            fileWriter = new FileWriter(file,true);
            properties.setProperty(key, value); // 存进map里面
            properties.store(fileWriter,""); // 将map对应的键值对写进输出流。
        } catch (IOException e) {
            // 卧槽我加入设置key,value失败,肯定调到这个逻辑
            return false;
        } finally {
            if (fileWriter != null) {  // 还是这样关比较好,万一报错就tm关不了
                try {
                    fileWriter.flush();
                    fileWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return true;
    }

}

测试文件

java 复制代码
@SpringBootTest
class IoDemoApplicationTests {

    @Test
    void contextLoads() {
        // 用户第一登录 ----,我们这里浏览器端不存token,只存用户名,更安全。
        String username = "qhx2005";
        String password = "123456";
        // 生成jwt
        JWTtUtils jwTtUtils = new JWTtUtils();
        String token = jwTtUtils.generatorJWTFromUserNameAndPassword(username, password);
        // 将jwt存进配置文件
        boolean success = IOUtils.setPropertiesKey(username, token);
        System.out.println("存进配置文件成功状态:"+success);
        assert success;


        // 用户登录后访问其他页面。检验token过期,拿出配置文件是否存在----
        // 获取token
        String token1 = IOUtils.getPropertiesKey(username);
        System.out.println(token1);
        // 检验token是否过期
        boolean overdue = jwTtUtils.checkTokenIsOverdue(token);
        // 本来这里如果token过期,我们响应一个状态码,让前端axios过滤器捕获到,删除本地username,重定向到登录页。
        System.out.println("已经过期:"+overdue);

    }

}
相关推荐
jnrjian4 分钟前
Library Cache Load Lock library cache pins are replaced by mutexes
java·后端·spring
hoiii1879 分钟前
基于MATLAB实现内点法解决凸优化问题
开发语言·matlab
abcnull13 分钟前
传统的JavaWeb项目Demo快速学习!
java·servlet·elementui·vue·javaweb
risc12345619 分钟前
【lucene】PostingsEnum跟TermsEnum 的区别是啥?
java·lucene
小江的记录本36 分钟前
【Kafka核心】Kafka高性能的四大核心支柱:零拷贝、批量发送、页缓存、压缩
java·数据库·分布式·后端·缓存·kafka·rabbitmq
SamDeepThinking40 分钟前
程序员过35岁之前,应该完成的三件事
java·后端·程序员
大数据三康1 小时前
Java字符统计:从输入到输出的完整解析
java·学习·循环结构
特种加菲猫1 小时前
多态:让代码拥有“千变万化”的能力
开发语言·c++
Mr_pyx1 小时前
【LeetHOT100】LRU缓存——Java多解法详解
java·开发语言