第十五章 加密算法实例1--注册登录(消息摘要算法)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第十五章 加密算法实例1--注册登录(消息摘要算法)相关的知识,希望对你有一定的参考价值。

15.1、原理步骤

  • 注册:注册时,将用户密码加密放入数据库
  • 登录:登录时,将用户密码采用上述相同的算法加密,之后再与数据库中的信息进行比对,若相同,则登录

15.2、实现(这里采用了SHA256算法,其他摘要算法MD5/SHA1/MAC类似)

注意:这里的程序是在我之前写的一个maven+spring+springmvc+mybatis+velocity整合的文章上进行的修改,具体的框架搭建以及数据库表结构等就不再啰嗦了,自己参考下边这篇博客:

http://www.cnblogs.com/java-zhao/p/5096811.html

这里只列出Java类。整个代码结构如下:

技术分享

UserController

技术分享
package com.xxx.web;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.xxx.model.User;
import com.xxx.service.UserService;

@Controller
@RequestMapping("user")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @ResponseBody
    @RequestMapping("register")
    public boolean register(@RequestParam("username") String username,
                            @RequestParam("password") String password){
        
        return userService.register(username, password);
    }
    
    @RequestMapping("login")
    public ModelAndView login(@RequestParam("username") String username,
                              @RequestParam("password") String password){
        User user = userService.login(username, password);
        
        ModelAndView modelAndView = new ModelAndView();
        if(user == null){
            modelAndView.addObject("message", "用户不存在或者密码错误!请重新输入");
            modelAndView.setViewName("error");
        }else{
            modelAndView.addObject("user", user);
            modelAndView.setViewName("userinfo");
        }
        
        return modelAndView;
    }
}
View Code

UserService(这里是加解密的主战场)

技术分享
package com.xxx.service;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.util.encoder.ShaEncoder;
import com.xxx.dao.UserDAO;
import com.xxx.model.User;

@Service
public class UserService {
    
    @Autowired
    private UserDAO userDao;
    
    public boolean register(String username, String password){
        User user = new User();
        user.setUsername(username);
        try {
            user.setPassword(ShaEncoder.encodeSHAHex(password));//对密码进行sha256加密
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return userDao.register(user);
    }
    
    public User login(String username, String password) {
        User user = null;
        try {
            user = userDao.login(username, ShaEncoder.encodeSHAHex(password));//对密码进行sha256加密
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return user;
    }
}
View Code

UserDAO

技术分享
package com.xxx.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.xxx.mapper.UserMapper;
import com.xxx.model.User;

@Repository
public class UserDAO {
    
    @Autowired
    private UserMapper userMapper;
    
    public boolean register(User user){
        return userMapper.insertUser(user)==1?true:false;
    }
    
    public User login(String username ,String password){
        return userMapper.selectByUsernameAndPwd(username, password);
    }
}
View Code

UserMapper

技术分享
package com.xxx.mapper;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

import com.xxx.model.User;

public interface UserMapper {
    
    @Insert("INSERT INTO userinfo(username, password) VALUES(#{username},#{password})")
    public int insertUser(User user);
    
    @Select("SELECT * FROM userinfo WHERE username = #{username} AND password = #{password}")
    @Results(value = { @Result(id = true, column = "id", property = "id"),
                       @Result(column = "username", property = "username"), 
                       @Result(column = "password", property = "password")})
    public User selectByUsernameAndPwd(@Param("username")String username ,@Param("password")String password);
}
View Code

ShaEncoder(这里基于Commons Codec,即CC实现的Sha256工具类)

技术分享
package com.util.encoder;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.codec.digest.DigestUtils;

public class ShaEncoder {
    private static final String ENCODING = "UTF-8";
    
    public static String encodeSHAHex(String data) throws NoSuchAlgorithmException,UnsupportedEncodingException {
        return new String(DigestUtils.sha256Hex(data.getBytes(ENCODING)));
    }
}
View Code

代码简单易懂,自己去看逻辑,然后进行测试即可。

当然我们还可以在上述代码的基础上,为密码加一点盐(即用一个字符串与密码相连),然后对加盐后的字符串进行加密。代码如下:

技术分享
package com.xxx.service;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.util.encoder.ShaEncoder;
import com.xxx.dao.UserDAO;
import com.xxx.model.User;

@Service
public class UserService {
    
    private static final String SALT = "nana";//
    
    @Autowired
    private UserDAO userDao;
    
    public boolean register(String username, String password){
        User user = new User();
        user.setUsername(username);
        try {
            user.setPassword(ShaEncoder.encodeSHAHex(SALT+password));//对加盐的密码进行sha256加密
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return userDao.register(user);
    }
    
    public User login(String username, String password) {
        User user = null;
        try {
            user = userDao.login(username, ShaEncoder.encodeSHAHex(SALT+password));//对加盐的密码进行sha256加密
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return user;
    }
}
View Code

当然,这里的盐是一个固定的字符串(在实际使用中,这样的做法最为常见),我们也可以对每个登录的用户使用他自己的姓名作为盐(这样每个人的盐就不一样了)。

 

以上是关于第十五章 加密算法实例1--注册登录(消息摘要算法)的主要内容,如果未能解决你的问题,请参考以下文章

算法导论第十五章

第十五章 原子变量和非阻塞同步机制

算法导论笔记——第十五章 动态规划

Andrew Ng-ML-第十五章-降维

第十五章 单点登录——《跟我学Shiro》

第十五章 软件架构之设计模式——单例模式