1.先上工具类MD5Util 目前真正用到的是直接MD5加密的方法 未使用自定义加工密码加密
package cn.cjq.util; import cn.cjq.entity.User; import java.security.MessageDigest;import java.util.Random; public class MD5Util { /** * 加工密码,和登录一致。 * @param user * @return */ public static User md5Pswd(User user){ //密码为 username + ‘#‘ + password,然后MD5 user.setPassword(md5Pswd(user.getUsername(),user.getPassword())); return user; } /** * 字符串返回值 * @param email * @param pswd * @return */ public static String md5Pswd(String email ,String pswd){ pswd = String.format("%s#%s", email,pswd); pswd = getMD5(pswd); return pswd; } /** * MD5 加密 * @param str * @return * @throws Exception */ public static String getMD5(String str) { MessageDigest messageDigest = null; try { messageDigest = MessageDigest.getInstance("MD5"); messageDigest.reset(); messageDigest.update(str.getBytes("UTF-8")); } catch (Exception e) { System.out.println("MD5转换异常!message:%s"+e.getMessage()); } byte[] byteArray = messageDigest.digest(); StringBuffer md5StrBuff = new StringBuffer(); for (int i = 0; i < byteArray.length; i++) { if (Integer.toHexString(0xFF & byteArray[i]).length() == 1) md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i])); else md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i])); } return md5StrBuff.toString(); } /** * 获取随机的数值。 * @param length 长度 * @return */ public static String getRandom620(Integer length){ String result = ""; Random rand = new Random(); int n = 20; if(null != length && length > 0){ n = length; } boolean[] bool = new boolean[n]; int randInt = 0; for(int i = 0; i < length ; i++) { do { randInt = rand.nextInt(n); }while(bool[randInt]); bool[randInt] = true; result += randInt; } return result; } /** * 加密解密算法 执行一次加密,两次解密 */ public static String convertMD5(String inStr){ char[] a = inStr.toCharArray(); for (int i = 0; i < a.length; i++){ a[i] = (char) (a[i] ^ ‘t‘); } String s = new String(a); return s; } }
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2.密码加密实例 注册时会使用(只需要将加密的密码存入数据库),传给UsernamePasswordToken的密码参数是未加密的密码,由密码匹配器去自动匹配
/** * 注册 && 登录 * @param vcode 验证码 * @return */ @RequestMapping(value="subRegister") @ResponseBody @SystemControllerLog(description = "用户注册登陆") public Response subRegister(@RequestParam(value="userName",required=false,defaultValue="") String userName, @RequestParam(value="passWord",required=false,defaultValue="") String passWord, @RequestParam(value="realname",required=false,defaultValue="") String realname, @RequestParam(value="userType",required=false,defaultValue="") String userType, @RequestParam(value="vcode",required=false,defaultValue="") String vcode)throws Exception{ //手机号不合法 if(!isMobileNO(userName)){ return new Response(ExceptionMsg.UserNameError); } //用户名已存在 User user = userServiceImpl.findByUserName(userName); if(null != user){ return new Response(ExceptionMsg.UserNameUsed); } //验证码错误 KeyValue data=(KeyValue)stringRedisServiceImpl.get(userName); if(data==null){ return new Response(ExceptionMsg.VcodeNotExists); }else if(!data.getValue().equals(vcode)){ return new Response(ExceptionMsg.VcodeError); } //把密码md5 String password = MD5Util.getMD5(passWord); //注册 User newuser =new User(); String uuid = UUID.randomUUID().toString().replaceAll("-", ""); newuser.setUerid(uuid); newuser.setAddtime(new Date()); newuser.setCreateperson(uuid); newuser.setUsername(userName); newuser.setEnditime(new Date()); newuser.setIsdelete(0); newuser.setStatus("1"); newuser.setPassword(password); newuser.setRealname(realname); newuser.setPhone(userName); newuser.setDifference(1); userServiceImpl.insertuser(newuser); //登陆验证 UsernamePasswordToken token = new UsernamePasswordToken(userName,passWord,false); SecurityUtils.getSubject().login(token); Session sessions = SecurityUtils.getSubject().getSession(); sessions.setAttribute("user",newuser ); //清理内存 stringRedisServiceImpl.remove(userName); return new Response(ExceptionMsg.SUCCESS);}--------------------------------------------------------------------------------------------------------------------------3.shiro.xml配置密码匹配器 两个bean 配置在自定义的realm里属性hashIterations的值目前为1,代表加密一次,其他值未试过,不明觉厉,待续
<!-- 凭证匹配器--><bean id="credentialsMatcher" class="cn.cjq.util.shiro.RetryLimitHashedCredentialsMatcher"> <constructor-arg ref="cacheManager"/> <property name="hashAlgorithmName" value="md5"/> <property name="hashIterations" value="1"/> <property name="storedCredentialsHexEncoded" value="true"/></bean>
<bean id="myShiroRealm" class="cn.cjq.util.shiro.UserRealm"> <!-- 配置密码匹配器 --> <property name="credentialsMatcher" ref="credentialsMatcher"/> <property name="cachingEnabled" value="true"/> <property name="authenticationCachingEnabled" value="true"/> <property name="authenticationCacheName" value="authenticationCache"/> <property name="authorizationCachingEnabled" value="true"/> <property name="authorizationCacheName" value="authorizationCache"/></bean>--------------------- ----------------------------------------------------------------------------------------------------------------4.自定义的密码匹配器 目前使用的md5
package cn.cjq.util.shiro; import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.ExcessiveAttemptsException;import org.apache.shiro.authc.credential.HashedCredentialsMatcher;import org.apache.shiro.cache.Cache;import org.apache.shiro.cache.CacheManager; import java.util.concurrent.atomic.AtomicInteger; public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher { private Cache<String, AtomicInteger> passwordRetryCache; public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) { passwordRetryCache = cacheManager.getCache("passwordRetryCache"); } @Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { String username = (String)token.getPrincipal(); //retry count + 1 AtomicInteger retryCount = passwordRetryCache.get(username); if(retryCount == null) { retryCount = new AtomicInteger(0); passwordRetryCache.put(username, retryCount); } if(retryCount.incrementAndGet() > 5) { //if retry count > 5 throw throw new ExcessiveAttemptsException(); } boolean matches = super.doCredentialsMatch(token, info); if(matches) { //clear retry count passwordRetryCache.remove(username); } return matches; }}
原文地址:https://www.cnblogs.com/1234cjq/p/8143745.html
时间: 2024-08-29 19:21:03