SpringBoot 实现密码加密以及登录成功token实现

谨以此文章记录自己的学习过程,借以帮助有同样需求的小伙伴,实现的不完善,只是将大概的主要内容实现而已~

一、demo所需的技术

springBoot、springSecurity、mysql、lombok

部分依赖pom.xml

<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-core</artifactId>
</dependency>

<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
</dependency>
<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<!--	生成token	-->
<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
			<version>0.9.1</version>
</dependency>

二、项目结构

 三、实现过程

 3.1数据库结构

application.yml  

这里配置mysql的驱动 以及设置端口号

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/bishi?my_db_01=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    show-sql: true
    properties:
      hibernate:
        format_sql: true
server:
  port: 8183

 DBUtil.class

这里将mysql的一些操作直接封装成一个实体类

package com.example.bcryptpasswordencoder.utils;

import java.sql.*;

public class DBUtil {
    static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://localhost:3306/my_db_01?useUnicode=true&characterEncoding=UTF-8";
    static final String USER = "root";
    static final String PASS = "root";

    static {
        try {
            Class.forName(JDBC_DRIVER);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    private Connection conn;
    private Statement stat;
    private PreparedStatement pstmt;

    public void openConnection() {
        try {
            conn = DriverManager.getConnection(DB_URL, USER, PASS);
            conn.setAutoCommit(true);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    public Statement getStatement() {
        openConnection();
        try {
            stat = conn.createStatement();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return stat;
    }
    public PreparedStatement getPreparedStatement(String sql) {
        openConnection();
        try {
            pstmt = conn.prepareStatement(sql);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return pstmt;
    }
    public void closeResource() {
        try {
            if (pstmt != null && !pstmt.isClosed()) {
                pstmt.close();
            }

            if (stat != null && !stat.isClosed()) {
                stat.close();
            }

            if (conn != null && !conn.isClosed()) {
                conn.close();
            }

        } catch (SQLException e) {
            // TODO: handle exception
            e.printStackTrace();
        }
    }
}

3.2 实体类 Users

这里习惯注意和数据库的字段名匹配比较好,以后用到mybatis这样的操作可以避免一些错误

@Data 的使用自动生成set和get方法

package com.example.bcryptpasswordencoder.entity;

import lombok.Data;

@Data
public class Users {
    private long id;
    private String username;
    private String password;
    private String usernike;
}

3.3 Dao层

该项目主要实现三个接口,添加用户、登录、和更新操作

package com.example.bcryptpasswordencoder.dao;

import java.util.Map;

public interface UsersDao {
//    添加用户 对密码进行加密
    Map<String,Object> bcryptPassword(String username,String password);
//    登录
    Map<String,Object> login(String username,String password);
//    更新昵称
    Map<String,Object> updateUserNick(String username,String usernick);
}

3.4 controller层

注册用户模块:主要是为了实现用户注册成功后,对存入数据库的密码进行加密(但是这里我没有实现对密码用户名的限定等等,你们自己可以deng

登录模块:这里主要是实现用户登录成功之后使用jwt生成token

更新模块:主要是为了实现使用token,对token的有效判断还有token解密,最后实现用户的更新操作

package com.example.bcryptpasswordencoder.controller;

import com.example.bcryptpasswordencoder.impl.UsersImpl;
import com.example.bcryptpasswordencoder.utils.JwtUtil;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@RequestMapping("/users")
@RestController
@CrossOrigin
public class UsersController {
    UsersImpl users = new UsersImpl();
//注册用户
    @PostMapping(value = "/bcryptPassword")
    public Map<String, Object> bcryptPassword(String username, String password) {
        Map<String,Object> map = new HashMap<>();
        map = users.bcryptPassword(username,password);
        return map;
    }
//登录
    @PostMapping(value = "/login")
    public  Map<String, Object> login(String username, String password){
        Map<String,Object> map = new HashMap<>();
        map = users.login(username,password);
        return map;
    }
//更新
    @PostMapping(value = "/updateUserNick")
    public Map<String,Object> updateUserNick(HttpServletRequest httpServletRequest, String userNick){
//        System.out.println(userNick);
        Map<String,Object> map = new HashMap<>();
//        首选判断token是否有效
        if(!JwtUtil.checkToken(httpServletRequest)){
            map.put("code",500);
            map.put("msg","token无效");
            return map;
        }
//        解密username
        String username = JwtUtil.getUserIdByJwtToken(httpServletRequest);
        map = users.updateUserNick(username,userNick);
        return map;
    }
}

3.5 impl

加密使用的是 BCryptPasswordEncoder 

我这里是为了顺便练习一下jdbc,大家觉得繁琐可以直接使用mybatis.

package com.example.bcryptpasswordencoder.impl;

import com.example.bcryptpasswordencoder.dao.UsersDao;
import com.example.bcryptpasswordencoder.entity.Users;
import com.example.bcryptpasswordencoder.utils.DBUtil;
import com.example.bcryptpasswordencoder.utils.JwtUtil;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class UsersImpl implements UsersDao {
    DBUtil dbUtil = new DBUtil();
    //        创建一个BCryptPasswordEncoder对象
    BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    @Override
    public Map<String, Object> bcryptPassword(String username, String password) {
//        对密码进行加密
        String password1 = passwordEncoder.encode(password);
        Map<String,Object> map = new HashMap<>();
//        数据库操作
        dbUtil.openConnection();
        PreparedStatement ps;
//        定义一个sql语句
        String sql="insert into users(username,password) values(?,?)";
        ps = dbUtil.getPreparedStatement(sql);
        int count=0;//判断sqlzhi
        try {
            ps.setString(1,username);
            ps.setString(2,password1);
            count = ps.executeUpdate();
//            关闭数据库连接
            dbUtil.closeResource();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        if(count>0) {
            map.put("code", 200);
            map.put("count", 0);
            map.put("msg", "添加用户成功");
            map.put("data", "");
        }else{
            map.put("code", 200);
            map.put("count", 0);
            map.put("msg", "添加用户失败");
        }

        return map;
    }

    @Override
    public Map<String, Object> login(String username, String password) {
        Map<String,Object> map = new HashMap<>();
        ArrayList<Users> users = new ArrayList<>();
//        通过username查找用户
//        定义sql语句
        String sql ="select * from users where username=?";
//        数据库操作
        dbUtil.openConnection();
        PreparedStatement ps;
        ps = dbUtil.getPreparedStatement(sql);
        try {
            ps.setString(1,username);
            ResultSet rs = ps.executeQuery();
            Users user;
            while(rs.next())
            {
                user = new Users();
                user.setId(rs.getInt("id"));
                user.setUsername(rs.getString("username"));
                user.setPassword(rs.getString("password"));
                users.add(user);
            }
            dbUtil.closeResource();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        if(users.size()>0){
//            证明有该用户
//            判断密码是否正确
           boolean matches  =  passwordEncoder.matches(password,users.get(0).getPassword());
//           生成token
           String token = JwtUtil.getJwtToken(users.get(0).getId(),users.get(0).getUsername());
           if(matches){
//               匹配成功
               map.put("code", 200);
               map.put("count", users.size());
               map.put("msg", "登录成功");
               map.put("data", users);
               map.put("token",token);
           }else{
               map.put("code", 500);
               map.put("count", 0);
               map.put("msg", "登录失败");
           }
        }
        return map;
    }

    @Override
    public Map<String, Object> updateUserNick(String username, String userNick) {
        Map<String,Object> map = new HashMap<>();
        int i= 0;//判断更新是否成功
//       数据库操作
        dbUtil.openConnection();
        PreparedStatement ps;
        try {
//                对昵称进行修改
//                定义sql语句
                String strSql = "update users set nickname = ? where username=?";
                ps = dbUtil.getPreparedStatement(strSql);
                ps.setString(1,userNick);
                ps.setString(2,username);
                i= ps.executeUpdate();
            dbUtil.closeResource();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        if(i>0){
            map.put("code", 200);
            map.put("count", 0);
            map.put("msg", "更新成功");
            map.put("data", "");
        }else{
            map.put("code", 500);
            map.put("count", 0);
            map.put("msg", "更新失败");
        }
        return map;
    }
}

3.6JwtUtil

这里大家如果不理解的话可以查阅这篇文章,写得很好https://blog.csdn.net/weixin_45070175/article/details/118559272

package com.example.bcryptpasswordencoder.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

public class JwtUtil {
//    token 时效 12小时
    public static final long EXPIRE = 1000*60*60*12;
//    签名哈希的密钥,对于不同的加密算法来说含义不同
    public static final String APP_SECRET = "hss200923usersToken";

    /**
     * 根据用户id和用户名生成token
     * @param id 用户id
     * @param username 用户名称
     * @return JWT规则生成的token
     */
    public static String getJwtToken(long id,String username){
        String JwtToken = Jwts.builder()
                .setHeaderParam("typ","JWT")
                .setHeaderParam("alg","HS256")
                .setSubject("users")
                .setIssuedAt(new Date())//token 保留时间
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))//token失效时间
                .claim("id",id)
                .claim("username",username)
//                HS256算法实际上就是MD5加盐值,此时APP_SECRET就代表盐值
                .signWith(SignatureAlgorithm.HS256,APP_SECRET)
                .compact();
        return JwtToken;
    }

    /**
     * 判断token是否存在与有效
     * @param jwtToken token字符串
     * @return 如果token 有效返回true,否则返回false
     */
    public static boolean checkToken(String jwtToken){
        if(StringUtils.isEmpty(jwtToken)) return false;
        try {
            Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        }catch(Exception e){
           e.printStackTrace();
           return false;
        }
        return true;
    }

    /**
     * 判断token 是否存在与有效
     * @param request
     * @return
     */
    public static boolean checkToken(HttpServletRequest request){
        try{
//            从http请求头中获取token字符串
            String jwtToken = request.getHeader("token");
            if(StringUtils.isEmpty(jwtToken)) return false;
            Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        }catch(Exception e){
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 根据token 获取用户username
     * @param request Http 请求对象
     * @return 解析token后获得的用户id
     */
    public static String getUserIdByJwtToken(HttpServletRequest request){
        String jwtToken = request.getHeader("token");
        if(StringUtils.isEmpty(jwtToken)) return "";
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(jwtToken);
        Claims claims = claimsJws.getBody();
        return (String)claims.get("username");
    }
}

四、操作

 

 

 

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 要实现Spring Boot Vue传输加密,可以采用以下步骤: 1. 在Spring Boot中使用HTTPS协议来加密传输数据。可以使用自签名证书或者购买正式的SSL证书。 2. 在Vue中使用HTTPS协议来加密传输数据。可以使用axios库来发送HTTPS请求。 3. 在Spring Boot中使用JWT(JSON Web Token)来对用户身份进行认证和授权。JWT可以在服务器端生成一个加密token,包含用户的身份信息和权限信息,然后在每次请求时将token发送给服务器进行验证。 4. 在Vue中使用JWT来对用户身份进行认证和授权。可以在登录成功后将服务器返回的token保存在本地,然后在每次请求时将token发送给服务器进行验证。 5. 在Spring Boot中使用Spring Security来对API进行保护。可以使用注解来限制API的访问权限,只允许已经认证和授权的用户访问。 6. 在Vue中使用路由守卫来对页面进行保护。可以在路由配置中使用beforeEach函数来判断用户是否已经认证和授权,如果没有则跳转到登录页面。 通过以上步骤,可以实现Spring Boot Vue传输加密,保护数据的安全性。 ### 回答2: 要实现Spring Boot和Vue之间的传输加密,可以采用以下步骤: 1. 在Spring Boot中配置HTTPS协议,以确保数据在传输过程中的安全性。可以使用自签名证书或第三方证书来配置HTTPS。 2. 在Spring Boot应用程序的配置文件中,设置以下属性来启用HTTPS: ```yaml server: port: 8443 # 设置HTTPS端口 ssl: key-store: classpath:keystore.jks # 设置SSL证书的路径 key-store-password: password # 设置SSL证书的密码 key-store-type: JKS # 设置SSL证书的类型 key-alias: tomcat # 设置SSL证书的别名 ``` 3. 在Vue应用程序中使用HTTPS协议来访问Spring Boot后端。可以使用axios库来发送HTTPS请求。 ```javascript import axios from 'axios'; axios.defaults.baseURL = 'https://your-domain.com'; // 设置Spring Boot后端的URL // 发送HTTPS POST请求 axios.post('/api/your-endpoint', { data }) .then(response => { // 处理响应数据 }) .catch(error => { // 处理错误 }); ``` 4. 可以使用JSON Web Token(JWT)来对请求进行加密和验证。在Spring Boot中,可以使用Spring Security和jjwt库来实现JWT的生成和验证。 ```java // 生成JWT token String token = Jwts.builder() .setSubject(username) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(SignatureAlgorithm.HS512, SECRET.getBytes()) .compact(); // 在请求中验证JWT token String token = request.getHeader("Authorization"); if (token != null && token.startsWith("Bearer ")) { // 验证token } ``` 通过以上步骤,可以实现Spring Boot和Vue之间的传输加密,确保数据在传输过程中的安全性和完整性。 ### 回答3: 要实现Spring Boot和Vue之间的数据传输加密,可以采用以下步骤: 1. 在Spring Boot后端应用中,可以使用Spring Security来实现数据传输加密。首先,配置HTTPS协议,可以通过自签名证书或者证书颁发机构(CA)签发的证书来实现。这样可以确保前后端之间的数据传输过程中是加密的。 2. 在Vue前端应用中,可以通过使用HTTPS协议访问后端API来保证数据传输的安全性。可以通过配置Vue的开发环境或者生产环境,将访问后端API的地址改为HTTPS协议。 3. 在Vue前端应用中,可以使用CryptJS等加密库来对敏感数据进行加密。例如,可以对用户密码等敏感信息进行加密传输,确保数据在前后端之间的传输过程中不被窃取或篡改。 4. 在Spring Boot后端应用中,可以使用JWT(JSON Web Token)来实现身份验证和安全传输。可以在用户登录成功后生成一个JWT,并将其返回给前端,前端每次请求通过将JWT放置在请求头中进行验证。这样可以确保数据传输的安全性和权限控制。 综上所述,通过配置HTTPS协议、使用加密库进行数据加密、使用JWT实现身份验证等方式,可以实现Spring Boot和Vue之间的数据传输加密,从而保证数据在传输过程中的安全性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值