之前发了一个登录表的设计,这里是设计实现的代码:网站登录设计

简单的用户表设计如上图:

代码如下所示:
随机加密算法6个:

package com.auth.sp.common.utils;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import sun.misc.BASE64Encoder;
import java.security.Key;
import java.security.MessageDigest;
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
/**
 * 作者: 薛俊鹏
 * 时间:2018/10/15 on  17:12 .
 * 描述:算法中心
 * 内容:这里记录描述了N种需要密钥的算法
 * 每种算法都会有一个特定的标识,根据标识锁定算法,最后在由MD5加密一次,加密的结果都保留大写
 * 状态: 编写/修改
 */
public class AlgorithmCenter {
    /**密钥算法**/
    public static final String KEY_ALGORITHM = "AES";
    /**加解密算法/工作模式/填充方式**/
    public static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
    private static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    /**
     * 加密数据 ral=1
     * @param data 待加密数据
     * @param key  密钥 16位
     * @return 加密后的数据
     * */
    public static String AESencrypt1(String data, String key) throws Exception {
        Key k = new SecretKeySpec(key.getBytes("UTF-8"), KEY_ALGORITHM);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM); //实例化Cipher对象,它用于完成实际的加密操作
        cipher.init(Cipher.ENCRYPT_MODE, k); //初始化Cipher对象,设置为加密模式
        return Base64.encode(cipher.doFinal(data.getBytes("UTF-8"))); //执行加密操作。加密后的结果用Base64编码进行传输
    }

    /**                                         ral = 1  end                     **/

    /**
     * 加密  ral=2
     * @param content
     *            需要加密的内容
     * @return
     */
    public static String AESencrypt2(String content,String key) {
        try {
            Cipher cipher = Cipher.getInstance("AES");// 创建密码器
            byte[] byteContent = content.getBytes("utf-8");
            cipher.init(Cipher.ENCRYPT_MODE, genKey(key));// 初始化
            byte[] result = cipher.doFinal(byteContent);
            return parseByte2HexStr(result); // 加密
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }

    /**
     * @mock 根据密钥获得 SecretKeySpec
     * @param strKey 加密解密密钥
     * @return
     */
    private  static SecretKeySpec genKey(String strKey){
        byte[] enCodeFormat = {0};
        try {
            KeyGenerator kgen = KeyGenerator.getInstance("AES");
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"  );
            secureRandom.setSeed(strKey.getBytes());
            kgen.init(128, secureRandom);
            SecretKey secretKey = kgen.generateKey();
            enCodeFormat = secretKey.getEncoded();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return new SecretKeySpec(enCodeFormat, "AES");
    }
    /**
     * 将二进制转换成16进制
     * @param buf
     * @return
     */
    private static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**                                         ral = 2  end                     **/


    /**
     * MD5加密 生成32位md5码
     */
    public static String AESencrypt3(String inStr,String key){
        MessageDigest md5 = null;
        try{
            md5 = MessageDigest.getInstance("MD5");
        }catch (Exception e){
            e.printStackTrace();
            return "";
        }
        char[] charArray = inStr.toCharArray();
        byte[] byteArray = new byte[charArray.length];

        for (int i = 0; i < charArray.length; i++)
            byteArray[i] = (byte) charArray[i];
        byte[] md5Bytes = md5.digest(byteArray);
        StringBuffer hexValue = new StringBuffer();
        for (int i = 0; i < md5Bytes.length; i++){
            int val = ((int) md5Bytes[i]) & 0xff;
            if (val < 16)
                hexValue.append("0");
            hexValue.append(Integer.toHexString(val));
        }
        return (hexValue.toString()+key).toUpperCase();
    }


    /**                                         ral = 3  end                     **/


    /**
     * base64加密 生成32位md5码
     */
    public static String AESencrypt4(String content,String key){
        byte[] bt = content.getBytes();
        String str = (new BASE64Encoder()).encodeBuffer(bt);
        return (str.trim()+key).toUpperCase();
    }



    /**                                         ral = 4  end                     **/
    /**
     * Takes the raw bytes from the digest and formats them correct.
     *
     * @param bytes the raw bytes from the digest.
     * @return the formatted bytes.
     */
    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        // 把密文转换成十六进制的字符串形式
        for (int j = 0; j < len; j++) {
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString().toUpperCase();
    }

    public static String AESencrypt5(String content,String key) {
        if (content == null) {
            return null;
        }
        try {
            MessageDigest messageDigest = MessageDigest.getInstance("SHA1");
            messageDigest.update(content.getBytes());
            return (getFormattedText(messageDigest.digest())+key);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**                                         ral = 5  end                     **/



/**
   * 利用java原生的摘要实现SHA256加密
   * @param str 加密后的报文
   * @return
   */
    public static String AESencrypt6(String content,String key){
        MessageDigest messageDigest;
        String encodeStr = "";
        try {
            messageDigest = MessageDigest.getInstance("SHA-256");
            messageDigest.update(content.getBytes("UTF-8"));
            encodeStr = byte2Hex(messageDigest.digest());
            } catch (Exception e) {
            e.printStackTrace();
            }
        return (encodeStr+key).toUpperCase();
       }

/**
   * 将byte转为16进制
   * @param bytes
   * @return
   */
    private static String byte2Hex(byte[] bytes){
        StringBuffer stringBuffer = new StringBuffer();
        String temp = null;
        for (int i=0;i<bytes.length;i++){
            temp = Integer.toHexString(bytes[i] & 0xFF);
            if (temp.length()==1){
                //1得到一位的进行补0操作
                stringBuffer.append("0");
                }
            stringBuffer.append(temp);
            }
        return stringBuffer.toString();
        }

    /**                                         ral = 6  end                     **/


        /*数据加密开始*/
    public static String GetAES(String value,int rand) throws  Exception{
        /*返回数据:加密数据+#+密钥*/
        String key_vue = "";
        /*密钥*/
        String km = "";
        GetKey key = new GetKey();
        switch (rand){
            case 1:
                km = key.KeyValue16();
                key_vue = ToMD5.MD5(AESencrypt1(value,km))+"#"+km;
                break;
            case 2:
                km = key.KeyValue32();
                key_vue = ToMD5.MD5(AESencrypt2(value,km))+"#"+km;
                break;
            case 3:
                km = key.KeyValue32();
                key_vue = ToMD5.MD5(AESencrypt3(value,km))+"#"+km;
                break;
            case 4:
                km = key.KeyValue32();
                key_vue = ToMD5.MD5(AESencrypt4(value,km))+"#"+km;
                break;
            case 5:
                km = key.KeyValue32();
                key_vue = ToMD5.MD5(AESencrypt5(value,km))+"#"+km;
                break;
            case 6:
                km = key.KeyValue32();
                key_vue = ToMD5.MD5(AESencrypt6(value,km))+"#"+km;
                break;
            default:
                km = key.KeyValue32();
                key_vue = ToMD5.MD5("JIAMISHUJUCUOWU")+"#"+km;
                break;
        }
        return key_vue;
    }

    /*数据加密开始,加密数据,算法,密钥*/
    public static String GetAESEnd(String value,int rand,String km) throws  Exception{
        /*返回数据:加密数据*/
        String key_vue = "";
        switch (rand){
            case 1:
                key_vue = ToMD5.MD5(AESencrypt1(value,km));
                break;
            case 2:
                key_vue = ToMD5.MD5(AESencrypt2(value,km));
                break;
            case 3:
                key_vue = ToMD5.MD5(AESencrypt3(value,km));
                break;
            case 4:
                key_vue = ToMD5.MD5(AESencrypt4(value,km));
                break;
            case 5:
                key_vue = ToMD5.MD5(AESencrypt5(value,km));
            case 6:
                key_vue = ToMD5.MD5(AESencrypt6(value,km));
                break;
            default:
                key_vue = ToMD5.MD5("JIAMISHUJUCUOWU");
                break;
        }
        return key_vue;
    }



}

 

 

 

转MD5:

package com.auth.sp.common.utils;

import java.security.MessageDigest;

/**
 * 作者: 薛俊鹏
 * 时间:2018/10/15 on  17:19 .
 * 描述:MD5算法
 * 内容:
 * 状态: 编写/修改
 */
public class ToMD5 {

    public static String MD5(String key) {
        char hexDigits[] = {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
        };
        try {
            byte[] btInput = key.getBytes();
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            return null;
        }
    }

}

 

登录方法:

package com.auth.sp.common.controller;
import com.auth.sp.common.aspect.ClearData;
import com.auth.sp.common.entity.LoginSystyem;
import com.auth.sp.common.entity.PwdKey;
import com.auth.sp.common.entity.SysKey;
import com.auth.sp.common.entity.SysUser;
import com.auth.sp.common.service.SysKeyService;
import com.auth.sp.common.service.SysUserService;
import com.auth.sp.common.shiro.ErrorReason;
import com.auth.sp.common.shiro.Token;
import com.auth.sp.common.utils.IPUtils;
import com.auth.sp.common.utils.Ognl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.List;

/**
 * 作者: 薛俊鹏
 * 时间:2018/10/12 on  17:55 .
 * 描述:登陆方法及控制 数据的拦截在权限机中处理 所有不合法的请求重置到登陆页面
 * 内容:
 * 状态: 编写/修改
 */
@RestController
public class LoginController {
    Log log = LogFactory.getLog(LoginController.class);
    @Autowired
    private SysUserService userService;
    @Autowired
    private SysKeyService keyService;

    /**登陆测试**/
    @RequestMapping(value = "log_in",method = RequestMethod.GET)
    public String Login(){
        List<SysUser> list = userService.SelectUser();
        SysUser user = new SysUser();
        for (int i = 0; i < list.size(); i++) {
            user = list.get(i);
            System.out.println("账户:"+user.getAccount());
        }
        return "OK-Account";
    }

    /**登录进入系统 全部返回json 数据**/
    @RequestMapping(value = "loginUser",method = RequestMethod.POST)
    public String LoginUser(@ModelAttribute LoginSystyem user, ModelMap model, HttpServletRequest request, HttpServletResponse response)
    throws Exception{
        /**用户信息判断**/
        if(Ognl.isEmpty(user) || Ognl.isEmpty(user.getAccount()) || Ognl.isEmpty(user.getPwd())){
            /**清空对象**/
            user = null;
            /**清空缓存数据**/
            response = ClearData.Clear(request,response);
            return ErrorReason.getErrorInfo(1).getErrorInfo();/*账户信息不能为空,请重新输入!*/
        }else{
            /**判断账户信息的准确性**/
            SysUser u = userService.selectByAccount(user.getAccount());
            /**用户不存在**/
            if(Ognl.isEmpty(u)){
                /**清空对象**/
                user = null;
                u = null;
                /**清空缓存数据**/
                response = ClearData.Clear(request,response);
                return ErrorReason.getErrorInfo(2).getErrorInfo();/*该账户信息不存在!*/
            }else{
                /**存在用户 记录登录IP**/
                u.setLogin_ip(IPUtils.getLocalIP());
                userService.updateByPrimaryKeySelective(u);
                /**根据用户id查询用户的密钥信息**/
                SysKey sysKey = keyService.selectByUserId(u.getId());
                if(Ognl.isEmpty(sysKey)){
                    log.info("sysKey数据异常,请及时处理!");
                    /**清空对象**/
                    user = null;
                    sysKey = null;
                    /**清空缓存数据**/
                    response = ClearData.Clear(request,response);
                    return ErrorReason.getErrorInfo(3).getErrorInfo();/*账户异常,请及时联系管理员!*/
                }else{
                    /**密码输入超过5次,踢出系统,清除登陆痕迹**/
                    if(u.getError_time()>=5){
                        /**清空对象**/
                        user = null;
                        user = null;
                        sysKey = null;
                        /**清空缓存数据**/
                        response = ClearData.Clear(request,response);
                        return "密码多次输入错误,"+ErrorReason.getErrorInfo(6).getErrorInfo();
                    }else {
                        /**数据置换,防止SQL攻击**/
                        PwdKey pwdKey = new PwdKey();
                        pwdKey.setKey(sysKey.getUser_key());
                        pwdKey.setValue(sysKey.getPwd());
                        pwdKey.setAccount(user.getPwd());
                        pwdKey.setNum(u.getAlg());
                        boolean isOk = SysUserController.IsPassPwd(pwdKey);
                        /**密码一致确认身份信息,密码不一致,踢出系统**/
                        if (!isOk) {
                            log.info(user.getAccount() + "密码输入错误!");
                            /**密码错误更新错误密码次数**/
                            u.setError_time(u.getError_time() + 1);
                            /**错误次数达到上限,冻结用户**/
                            if (u.getError_time() >= 5) {
                                u.setFreeze(0);
                                u.setReason("密码输入错误次数超过5次");
                            }
                            userService.updateByPrimaryKeySelective(u);
                            /**清空对象**/
                            user = null;
                            pwdKey = null;
                            user = null;
                            sysKey = null;
                            /**清空缓存数据**/
                            response = ClearData.Clear(request, response);
                            return ErrorReason.getErrorInfo(4).getErrorInfo();/*密码输入错误*/
                        } else {
                            if(u.getFreeze()==0){
                                /**清空对象**/
                                user =  null;
                                u = null;
                                pwdKey = null;
                                sysKey = null;
                                /**清空缓存数据**/
                                response = ClearData.Clear(request, response);
                                return ErrorReason.getErrorInfo(6).getErrorInfo()+"请联系管理员处理!";
                            }else {
                                /**更新用户信息**/
                                u.setError_time(0);
                                u.setReason("");
                                userService.updateByPrimaryKeySelective(u);
                                log.info(u.getAccount() + "欢迎进入系统...");
                                /**进入系统之后,全称使用加密的身份验证,验证失败,或者超时,踢出系统**/
//                                request.getSession().setAttribute("token", Token.EncryMacSHA(u.getAccount()));
                                request.getSession().setAttribute("uname1",u.getAccount());
                                HttpSession session = request.getSession();
                                request.getSession().setAttribute("u",u);
                                session.setAttribute("token",Token.EncryMacSHA(u.getAccount()));
                                session.setAttribute("uname",u.getAccount());
                                pwdKey = null;
                                user = null;
                                sysKey = null;
                                String result = ErrorReason.getErrorInfo(5).getErrorCode();/*授权通过*/
                                return result;
                            }
                        }
                    }
                }
            }
        }
    }


}

 

数据清除:

package com.auth.sp.common.aspect;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;

/**
 * 作者: 薛俊鹏
 * 时间:2018/10/22 on  10:53 .
 * 描述:主要用于数据的清空和初始化处理
 * 内容:
 * 状态: 编写/修改
 */
public class ClearData {

    /**session的初始化和清空操作**/
    public static void initSession(HttpServletRequest request){
        /**获取所有session 枚举**/
        Enumeration em = request.getSession().getAttributeNames();
        while(em.hasMoreElements()){
            request.getSession().removeAttribute(em.nextElement().toString());
        }
    }

    /**清空cookie**/
    public static HttpServletResponse CleanCookies(HttpServletRequest request,HttpServletResponse response){
        /**获取所有cookie信息**/
        Cookie[] cookies=request.getCookies();
        for(Cookie cookie: cookies){
      /**使用完立即删除**/
            cookie.setMaxAge(0);
      /**所有路径下的cookie**/
            cookie.setPath("/");
            response.addCookie(cookie);
        }
        return response;
    }

    public static HttpServletResponse Clear(HttpServletRequest request,HttpServletResponse response){
        /**清空session**/
        ClearData.initSession(request);
        request.getSession().invalidate();
        /**清空cookie**/
        response = ClearData.CleanCookies(request,response);
        return response;
    }

}


错误信息封装:

package com.auth.sp.common.shiro;

/**
 * 作者: 薛俊鹏
 * 时间:2018/10/25 on  11:42 .
 * 描述:错误定义
 * 内容:
 * 状态: 编写/修改
 */
public class ErrorBean {
    /**错误标识**/
    private int identification;
    /**错误代码**/
    private String errorCode;
    /**错误中文**/
    private String errorInfo;
    /**错误英文**/
    private String errorMsg;

//    get   set

    public int getIdentification() {
        return identification;
    }

    public void setIdentification(int identification) {
        this.identification = identification;
    }

    public String getErrorCode() {
        return errorCode;
    }

    public void setErrorCode(String errorCode) {
        this.errorCode = errorCode;
    }

    public String getErrorInfo() {
        return errorInfo;
    }

    public void setErrorInfo(String errorInfo) {
        this.errorInfo = errorInfo;
    }

    public String getErrorMsg() {
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
        this.errorMsg = errorMsg;
    }
}

 

 

错误信息配置:

package com.auth.sp.common.shiro;

/**
 * 作者: 薛俊鹏
 * 时间:2018/10/25 on  11:41 .
 * 描述:定义错误信息
 * 内容:
 * 状态: 编写/修改
 */
public class ErrorReason {

    public static ErrorBean getErrorInfo(int identification) {
        String code = "9999";/*错误代码*/
        String info = "未知错误";/*中文信息*/
        String errorMsg = "unknown error";/*英文解释*/
        switch (identification) {
            case 1:
                code = "N0001";
                info = "账户信息不能为空,请重新输入!";
                errorMsg = "Account information can not be empty. Please re-enter it!";
                break;
            case 2:
                code = "N0002";
                info = "该账户信息不存在!";
                errorMsg = "The account information does not exist!";
                break;
            case 3:
                code = "N0003";
                info = "账户异常,请及时联系管理员!";
                errorMsg = "Account exception, please contact the administrator in time!";
                break;
            case 4:
                code = "N0004";
                info = "密码输入错误,请重新输入!";
                errorMsg = "Password input error, please re input!";
                break;
            case 5:
                code = "N0005";
                info = "授权通过!";
                errorMsg = "Permit passage!";
                break;
            case 6:
                code = "N0006";
                info = "账户已被系统冻结!";
                errorMsg = "The account has been frozen!";
                break;
            default:
                code = "N9999";
                info = "未知异常,请联系管理员!";
                errorMsg = "Unknown exception, please contact the administrator!";
                break;
        }
        ErrorBean errorInfo = new ErrorBean();
        errorInfo.setErrorCode(code);
        errorInfo.setErrorInfo(info);
        errorInfo.setErrorMsg(errorMsg);
        return errorInfo;
    }

}
 

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
⽤户登录系统数据库设计 ⽤户登录系统数据库设计 最近看了看公司后台⽤户登录系统的设计, ⽐较混乱, 主要还是因为URS和Oauth以及URS第三⽅这三个登录形式各不相同导致的。 下⾯着重介绍⼀下涉及到第三⽅登录中需要注意的问题 在⼀个新项⽬中, 如果是要建⽴⾃⼰的登录体系的话, 那么直接创建⼀个Users,包含username和password两列,这样,就可以实现登录了: id " username " password " name等其他字段 ----+----------+----------+---------------- A1 " bob " a1b23f2c " ... A2 " adam " c0932f32 " ... 如果要让⽤户通过第三⽅登录,⽐如微博登录或QQ登录,怎么集成进来呢? 以微博登录为例,由于微博使⽤OAuth2协议登录,所以,⼀个登录⽤户会包含他的微博⾝份的ID,⼀个Access Token⽤于代该⽤户访问微博的API和⼀个过期时间。 要集成微博登录,很多童鞋⽴刻想到把Users扩展⼏列,记录下微博的信息: id " username " password " weibo_id " weibo_access_token " weibo_expires " name等其他字段 ----+----------+----------+----------+--------------------+---------------+---------------- A1 " bob " a1b23f2c " W-012345 " xxxxxxxxxx " 604800 " ... A2 " adam " c0932f32 " W-234567 " xxxxxxxxxx " 604800 " ... 加⼀个QQ登录Users就⼜需要加3列,⾮常不灵活 那么我们需要对这个进⾏拆分。当⽤户以任意⼀种⽅式登录成功后,我们读取到的总是Users对应的⼀⾏记录,它实际上是⽤户的个⼈资料(Profile),⽽登录过程只是为了 认证⽤户(Authenticate),⽆论是本地⽤密码验证,还是委托第三⽅登录,这个过程本质上都是认证。 所以,如果把Profile和Authenticate分开,就⼗分容易理解了。Users本⾝只存储⽤户的Profile, 其中ID为关联不同登录⽅式的外键。 id " name " birth等其他字段 ----+------+----------------- A1 " Bob " ... A2 " Adam " ... ⽽通过⽤户名⼝令登录可视为⼀种Authenticate的⽅式,利⽤LocalAuth维护: id " user_id " username " password ----+---------+----------+----------- 01 " A1 " bob " a1b23f2c 02 " A2 " adam " c0932f32 通过微博登录可视为另⼀种Authenticate⽅式,利⽤OAuth维护, 但是access_token⼀般情况也只有⼏个⼩时的时效, 所以存储它是没有意义的, 每次登录的时候去微博后台 验证⼀下客户端传来的token就⾏了。 如果⽤户只⽤了第三⽅登录, 那就拿第三⽅数据来填充刚才的User即可。 id " user_id " weibo_id " ----+---------+----------+ 11 " A1 " W-012345 " 12 " A2 " W-234567 " 如果要添加另⼀种OAuth登录,⽐如QQ登录,那就再加⼀个列标⽰不同站点也就OK了, 但是要注意⽤户在不同登录⽅式的⽤户名和photo⼀般不⼀样, 所以也单独存起来 id " user_id " oauth_name " oauth_id " nick_name" photo" ----+---------+------------+----------+----------+------+ 11 " A1 " weibo " W-012345 " 12 " A2 " weibo " W-234567 " 13 " A1 " qq " Q-090807 " 14 " A2 " qq " Q-807060 " 通过这种⽅式, ⽆论⽤户采⽤哪种⽅式登录, 都可以锁定到⽤户的user_id。 下⾯再说⼀下⽹易的URS登录, 因为我们要直接采⽤⽹易通⾏证, 所以也就不需⾃⼰存储密码, 因此我们的架构应该设为User id " user_Email " username " birth ----+------------+----------
好的,我可以为你提供一些关于在 Pycharm 中实现 MySQL 数据库和设计一个 GUI 页面的指导。 首先,你需要安装 MySQL 数据库和 PyMySQL 模块。可以在终端中使用以下命令来安装: ``` pip install pymysql ``` 接下来,你需要在 MySQL 中创建一个数据库和一个来存储学生信息。可以使用以下命令来创建: ```sql CREATE DATABASE student_db; USE student_db; CREATE TABLE student ( id INT(11) NOT NULL AUTO_INCREMENT, name VARCHAR(255) NOT NULL, age INT(11) NOT NULL, gender VARCHAR(255) NOT NULL, PRIMARY KEY (id) ); ``` 这里我们创建了一个名为 student_db 的数据库,并且在其中创建了一个名为 student 的,包括 id、name、age 和 gender 四个字段。 接下来,你可以使用 Pycharm 中的 GUI 工具来设计一个 GUI 页面,用来添加、删除和查找学生信息。 可以使用 PyQt、Tkinter 等 GUI 工具包来实现,这里我以 PyQt5 为例来演示: 首先,你需要在 Pycharm 中创建一个 PyQt5 项目,然后在项目中创建一个 Python 文件,比如叫做 student_management_system.py。 然后,你可以在该文件中编写代码实现 GUI 页面。具体来说,你需要设计一个窗口、标签、文本框、按钮等控件,并且为按钮添加事件响应函数,用来实现添加、删除和查找学生信息的功能。 比如: ```python import sys from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QLineEdit, QPushButton, QMessageBox import pymysql class StudentManagementSystem(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setGeometry(300, 300, 300, 250) self.setWindowTitle('学生信息管理系统') self.name_label = QLabel('姓名:', self) self.name_label.move(20, 20) self.name_edit = QLineEdit(self) self.name_edit.move(80, 20) self.age_label = QLabel('年龄:', self) self.age_label.move(20, 60) self.age_edit = QLineEdit(self) self.age_edit.move(80, 60) self.gender_label = QLabel('性别:', self) self.gender_label.move(20, 100) self.gender_edit = QLineEdit(self) self.gender_edit.move(80, 100) self.add_button = QPushButton('添加', self) self.add_button.move(20, 150) self.add_button.clicked.connect(self.add_student) self.remove_button = QPushButton('删除', self) self.remove_button.move(100, 150) self.remove_button.clicked.connect(self.remove_student) self.find_button = QPushButton('查找', self) self.find_button.move(180, 150) self.find_button.clicked.connect(self.find_student) self.show() def add_student(self): name = self.name_edit.text() age = self.age_edit.text() gender = self.gender_edit.text() if name and age and gender: try: conn = pymysql.connect(host='localhost', port=3306, user='root', password='123456', db='student_db') cursor = conn.cursor() sql = "INSERT INTO student (name, age, gender) VALUES (%s, %s, %s)" cursor.execute(sql, [name, age, gender]) conn.commit() QMessageBox.information(self, '提示', '添加成功!') except: QMessageBox.warning(self, '警告', '添加失败!') finally: cursor.close() conn.close() else: QMessageBox.warning(self, '警告', '请输入完整信息!') def remove_student(self): name = self.name_edit.text() if name: try: conn = pymysql.connect(host='localhost', port=3306, user='root', password='123456', db='student_db') cursor = conn.cursor() sql = "DELETE FROM student WHERE name=%s" cursor.execute(sql, [name]) conn.commit() if cursor.rowcount > 0: QMessageBox.information(self, '提示', '删除成功!') else: QMessageBox.warning(self, '警告', '该学生不存在!') except: QMessageBox.warning(self, '警告', '删除失败!') finally: cursor.close() conn.close() else: QMessageBox.warning(self, '警告', '请输入学生姓名!') def find_student(self): name = self.name_edit.text() if name: try: conn = pymysql.connect(host='localhost', port=3306, user='root', password='123456', db='student_db') cursor = conn.cursor() sql = "SELECT * FROM student WHERE name=%s" cursor.execute(sql, [name]) result = cursor.fetchone() if result: QMessageBox.information(self, '学生信息', '姓名:{}\n年龄:{}\n性别:{}'.format(result[1], result[2], result[3])) else: QMessageBox.warning(self, '警告', '该学生不存在!') except: QMessageBox.warning(self, '警告', '查找失败!') finally: cursor.close() conn.close() else: QMessageBox.warning(self, '警告', '请输入学生姓名!') if __name__ == '__main__': app = QApplication(sys.argv) ex = StudentManagementSystem() sys.exit(app.exec_()) ``` 这里我们创建了一个 StudentManagementSystem 类,继承自 QWidget 类,用来示我们的 GUI 窗口。然后我们在 initUI 方法中设计了窗口、标签、文本框、按钮等控件,并且为按钮添加了事件响应函数,用来实现添加、删除和查找学生信息的功能。 在按钮的事件响应函数中,我们使用 PyMySQL 模块来连接 MySQL 数据库,并且执行 SQL 语句来实现相应的功能。在执行 SQL 语句之前,我们需要先从文本框中获取用户输入的学生信息。 最后,在 if __name__ == '__main__' 中,我们创建了一个 QApplication 对象,并且将我们的 StudentManagementSystem 对象加入到该对象中,然后调用 app.exec_() 方法来启动 GUI 程序。 这里需要注意的是,我们在 SQL 语句中使用了格式化字符串来传递参数,这可以有效地防止 SQL 注入攻击。另外,在连接 MySQL 数据库之前,你需要先启动 MySQL 服务。 希望这些内容能够帮助到你,如有不足之处还请指正。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值