JAVA 登录加盐验证和颁发身份令牌

     加盐的目是:    
             即使数据被拖库,攻击者也无法从中破解出用户的密码。
             即使数据被拖库,攻击者也无法伪造登录请求通过验证。
             即使数据被拖库,攻击者劫持了用户的请求数据,也无法破解出用户的密码。

     思路:
     1.先得到用户的账号和密码
    String username = request.getParameter("username");//接受用户账号

    String password = request.getParameter("password");//接受用户密码
    2.在得到的账号中去数据库里查询是否存在
    3.账号存在,取出数据库里加盐的字段和密码

ps:这里取出来的密码是之前注册的时候已经加盐好了
4.把用户的密码md5一下拼接加盐后,在md5一下!

5.最后在颁发身份令牌

登录代码


package spring_servlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.auth0.jwt.interfaces.DecodedJWT;

import net.sf.json.JSONObject;
import springDao.BaseController;
import springEntity.mt_admin;
import spring_service.mt_adminService;

public class mt_adminServlet extends HttpServlet {
	 private BaseController cont = new BaseController();
	/*
	 * Get请求
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		PrintWriter out = response.getWriter();
		request.setCharacterEncoding("utf-8");// 设置中文
		response.setContentType("text/html;charset=utf-8");// 设置中文

		String action = request.getParameter("op");// 获取页面中op对象
		if ("login".equals(action)) {
			login(request, response);
		} else if ("test".equals(action)) {
			Test(request, response);
		} else {
			out.print("参数错误");
		}
	}

	/*
	 * 登录
	 * @param username用户名
	 * @param password密码
	 */
	private void login(HttpServletRequest request, HttpServletResponse response) throws IOException {
		PrintWriter out = response.getWriter();
		String username = request.getParameter("username");// GET或POST都可得到参数
		String password = request.getParameter("password");
		if (username == null || password == null) {
			out.print("{'error':-3,'message':'参数错误'}");
			return;
		}
		mt_adminService AdminService = new mt_adminService();
		mt_admin admin = AdminService.getAdmin(username);// 调用mt_adminService里getAdmin的方法
		if (admin == null) {
			out.print("{'error':-1,'message':'账号不存在'}");
			return;
		}
		//公共类
	
		String Md = cont.getMD5(cont.getMD5(password) + admin.getSalt());// 原密码加盐在md5
		if (!Md.equals(admin.getPassword())) {// 对比枚举后的密码是否和数据库的密码相同
			out.print("{'error':-1,'message':'密码错误'}");
			return;
		}

		//颁发身份令牌
		String jwt = cont.HS256(admin.getToken());
		String xiaozhang = "{'username':'" + admin.getUsername() + "','jwt':'" + jwt + "'}";
		Cookie cookie = new Cookie("xiaozhang", xiaozhang);
		cookie.setMaxAge(60*60);// 设置其1小时的生命周期 设置 0是删除cookie
		cookie.setPath("/");// 设置cookie的路径
		response.addCookie(cookie);// 添加cookie

		out.print("{'error':0,'message':'登录成功'}");//网页端输出
		System.err.println("登录成功");// 控制台输出
	}

	/*
	 * 测试有没有登录过
	 */
	private void Test(HttpServletRequest request, HttpServletResponse response) throws IOException {
		PrintWriter out = response.getWriter();
		Cookie[] AdminCookie = request.getCookies();// 获取当前cookie
		JSONObject strJson = null;
		// 如果没有任何的Cookie
		if (AdminCookie == null) {
			out.print("{'error':-2,'message':'未登录'}");
			return;
		}
		// 循环所有Cookie找出里面是否有名为xiaozhang的Cookie
		for (Cookie val : AdminCookie) {
			if (val.getName().equals("xiaozhang")) {
				strJson = JSONObject.fromObject(val.getValue());// 转成json
			}
		}
		// 找不到xiaozhang的Cookie
		if (strJson == null) {
			out.print("{'error':-2,'message':'未登录'}");
			return;
		}
		mt_adminService AdminService = new mt_adminService();
		mt_admin admin = AdminService.getAdmin(strJson.getString("username"));
		if (admin == null) {// 找不到该用户
			out.print("{'error':-3,'message':'登录过期,请重新登录'}");
			return;
		}
		// 验证身份
		DecodedJWT jwt = cont.JHS256(admin.getToken(), strJson.getString("jwt"));
		if (jwt == null) {// 身份令牌不匹配
			out.print("{'error':-3,'message':'登录过期,请重新登录'}");
			return;
		}
		out.print("{'error':0,'message':'登录成功'}");
		System.err.println("{'error':0,'message':'登录成功'}");
	}

	/*
	 * Post提交
	 */
	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);// 转到GET提交里去
	}

}


把公共类的代码贴出来
package springDao;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.Date;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;

//常用的参数
public class BaseController {
	 /**
     * 对字符串md5加密(小写+字母)
     *
     * @param str 传入要加密的字符串
     * @return  MD5加密后的字符串
     */
    public static String getMD5(String str) {
        try {
            // 生成一个MD5加密计算摘要
            MessageDigest md = MessageDigest.getInstance("MD5");
            // 计算md5函数
            md.update(str.getBytes());
            // digest()最后确定返回md5 hash值,返回值为8为字符串。因为md5 hash值是16位的hex值,实际上就是8位的字符
            // BigInteger函数则将8位的字符串转换成16位hex值,用字符串来表示;得到字符串形式的hash值
            return new BigInteger(1, md.digest()).toString(16);
        } catch (Exception e) {
           e.printStackTrace();
           return null;
        }
    }
    
    /**
     * 生成随机数
     *
     */
    public static String makeOrderNums(){
   	 String datenum="";
   	 datenum=DateUtils.getStrByDate(new Date(),"yyyMMddHHmmss");
   	 String num=""+ (int)(Math.random()*10)+(int)(Math.random()*10)+(int)(Math.random()*10)+(int)(Math.random()*10);
   	 return datenum+num;
    }
    
    
    /**
     * Example using HS256算法
     * @param secret 保存的秘密
     */
    public static String HS256(String id){
    	String token =null;
    	try {
    	    Algorithm algorithm = Algorithm.HMAC256(id);//唯一id
    	         token = JWT.create()
    	        .withIssuer("auth0")
    	        .sign(algorithm);
    	} catch (UnsupportedEncodingException exception){
    	    //不支持UTF-8
    	} catch (JWTCreationException exception){
    	    //Invalid Signing configuration / Couldn't convert Claims.
    	}
		return token;
    }
    
    /**
     * Example using HS256解法
     * @param token HS256算法加密后的字符串
     * jwt 返回为null者说明身份验证失败
     */
    public static DecodedJWT JHS256(String id,String token){
    	 DecodedJWT jwt = null;
    	try {
    	    Algorithm algorithm = Algorithm.HMAC256(id);//唯一id
    	    JWTVerifier verifier = JWT.require(algorithm)
    	        .withIssuer("auth0")
    	        .build(); //Reusable verifier instance
    	        jwt = verifier.verify(token);
    	} catch (UnsupportedEncodingException exception){
    	    //UTF-8 encoding not supported
    	} catch (JWTVerificationException exception){
    	    //Invalid signature/claims
    	}
		return jwt;
    }
}


  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这个问题属于技术问题,关于Java结合SpringBoot给登录写个用户名和密码JWT令牌验证,你可以参考以下步骤: 1. 在SpringBoot项目的pom.xml文件中添JWT依赖: ``` <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt</artifactId> <version>0.9.1</version> </dependency> ``` 2. 编写一个jwt工具类,该类用于生成和解析JWT令牌: ``` public class JwtUtils { private static final long EXPIRE_TIME = 30 * 60 * 1000; // 过期时间为30分钟 private static final String SECRET_KEY = "your_secret_key"; // 自定义秘钥,用于签名和解密 public static String generateToken(String username) { Date now = new Date(); Date expireTime = new Date(now.getTime() + EXPIRE_TIME); return Jwts.builder() .setSubject(username) .setIssuedAt(now) .setExpiration(expireTime) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } public static String getUsernameFromToken(String token) { Claims claims = Jwts.parser() .setSigningKey(SECRET_KEY) .parseClaimsJws(token) .getBody(); return claims.getSubject(); } public static boolean validateToken(String token) { try { Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token); return true; } catch (Exception e) { return false; } } } ``` 3. 编写一个登录接口,该接口接收用户名和密码参数,并返回生成的JWT令牌: ``` @RestController public class LoginController { @PostMapping("/login") public RespBean login(@RequestParam("username") String username, @RequestParam("password") String password) { // TODO: 在此处校验用户名和密码是否正确 String token = JwtUtils.generateToken(username); return RespBean.success(token); } } ``` 4. 在需要验证访问权限的接口中,使用Spring Security和JWT进行验证: ``` @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/login").permitAll() .anyRequest().authenticated() .and() .addFilter(new JwtAuthenticationFilter(authenticationManager())) .addFilter(new JwtAuthorizationFilter(authenticationManager(), userDetailsService)); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder()); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } } public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter { @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { try { String username = request.getParameter("username"); String password = request.getParameter("password"); Authentication authentication = new UsernamePasswordAuthenticationToken( username, password, Collections.emptyList()); return getAuthenticationManager().authenticate(authentication); } catch (Exception e) { throw new RuntimeException(e); } } } public class JwtAuthorizationFilter extends BasicAuthenticationFilter { private final UserDetailsService userDetailsService; public JwtAuthorizationFilter(AuthenticationManager authenticationManager, UserDetailsService userDetailsService) { super(authenticationManager); this.userDetailsService = userDetailsService; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { String header = request.getHeader("Authorization"); if (header == null || !header.startsWith("Bearer ")) { chain.doFilter(request, response); return; } String token = header.replace("Bearer ", ""); if (JwtUtils.validateToken(token)) { String username = JwtUtils.getUsernameFromToken(token); UserDetails userDetails = userDetailsService.loadUserByUsername(username); UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authentication); } chain.doFilter(request, response); } } ``` 我希望上述内容对你有所帮助,如果需要了解更详细的内容,可以自行查询相关资料。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值