日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Shrio 自定义算法登录认证

發布時間:2024/10/6 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Shrio 自定义算法登录认证 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.實現shrio SimpleCredentialsMatcher的doCredentialsMatch算法

package cn.steven.manager.security;import cn.sh.ideal.manager.util.AESUtils; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.credential.SimpleCredentialsMatcher; import org.slf4j.Logger; import org.slf4j.LoggerFactory;/*** @FileName: CustomCredentialsMatcher* @Author Steven* @Date: 2021/11/17*/ public class CustomCredentialsMatcher extends SimpleCredentialsMatcher{private Logger logger = LoggerFactory.getLogger(getClass());@Overridepublic boolean doCredentialsMatch(AuthenticationToken authenticationToken, AuthenticationInfo info) {//獲得前臺傳過來的密碼SystemUsernamePasswordToken token = (SystemUsernamePasswordToken) authenticationToken;//這是數據庫里查出來的密碼String sqlOriginalPassword=(String)info.getCredentials();boolean flag = AESUtils.aesEncrypt(String.valueOf(token.getPassword())).equals(sqlOriginalPassword);return flag;} }

2.自定義算法

package cn.sh.ideal.manager.util;import org.apache.commons.codec.binary.Base64; import sun.misc.BASE64Decoder;import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.spec.SecretKeySpec; import java.math.BigInteger;/*** AES的加密和解密* @author libo*/ public class AESUtils {/*** 密鑰 (需要前端和后端保持一致)*/private static final String KEY = "abcdefgabcdefg12";/*** 算法*/private static final String ALGORITHMSTR = "AES/ECB/PKCS5Padding";/** * aes解密 * @param encrypt 內容 * @return * @throws Exception */ public static String aesDecrypt(String encrypt) { try {return aesDecrypt(encrypt, KEY);} catch (Exception e) {e.printStackTrace();return "";} } /** * aes加密 * @param content * @return * @throws Exception */ public static String aesEncrypt(String content) { try {return aesEncrypt(content, KEY);} catch (Exception e) {e.printStackTrace();return "";} } /** * 將byte[]轉為各種進制的字符串 * @param bytes byte[] * @param radix 可以轉換進制的范圍,從Character.MIN_RADIX到Character.MAX_RADIX,超出范圍后變為10進制 * @return 轉換后的字符串 */ public static String binary(byte[] bytes, int radix){ return new BigInteger(1, bytes).toString(radix);// 這里的1代表正數} /** * base 64 encode * @param bytes 待編碼的byte[] * @return 編碼后的base 64 code */ public static String base64Encode(byte[] bytes){ return Base64.encodeBase64String(bytes);} /** * base 64 decode * @param base64Code 待解碼的base 64 code * @return 解碼后的byte[] * @throws Exception */ public static byte[] base64Decode(String base64Code) throws Exception{ return StringUtils.isEmpty(base64Code) ? null : new BASE64Decoder().decodeBuffer(base64Code);} /** * AES加密 * @param content 待加密的內容 * @param encryptKey 加密密鑰 * @return 加密后的byte[] * @throws Exception */ public static byte[] aesEncryptToBytes(String content, String encryptKey) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES");kgen.init(128); Cipher cipher = Cipher.getInstance(ALGORITHMSTR);cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(encryptKey.getBytes(), "AES"));return cipher.doFinal(content.getBytes("utf-8")); } /** * AES加密為base 64 code * @param content 待加密的內容 * @param encryptKey 加密密鑰 * @return 加密后的base 64 code * @throws Exception */ public static String aesEncrypt(String content, String encryptKey) throws Exception { return base64Encode(aesEncryptToBytes(content, encryptKey)); } /** * AES解密 * @param encryptBytes 待解密的byte[] * @param decryptKey 解密密鑰 * @return 解密后的String * @throws Exception */ public static String aesDecryptByBytes(byte[] encryptBytes, String decryptKey) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); kgen.init(128); Cipher cipher = Cipher.getInstance(ALGORITHMSTR); cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(decryptKey.getBytes(), "AES")); byte[] decryptBytes = cipher.doFinal(encryptBytes); return new String(decryptBytes); } /** * 將base 64 code AES解密 * @param encryptStr 待解密的base 64 code * @param decryptKey 解密密鑰 * @return 解密后的string * @throws Exception */ public static String aesDecrypt(String encryptStr, String decryptKey) throws Exception { return StringUtils.isEmpty(encryptStr) ? null : aesDecryptByBytes(base64Decode(encryptStr), decryptKey); } /*** 測試*/public static void main(String[] args) throws Exception { String encrypt = "SiDMeIRxC/HVG149ftRayg==";System.out.println("加密后:" + encrypt);String decrypt = aesDecrypt(encrypt, KEY);System.out.println("解密后:" + decrypt); } }

3.設置定義算法

package cn.sh.ideal.manager.security;import java.io.Serializable; import java.util.Collection; import java.util.List; import java.util.concurrent.TimeUnit;import javax.annotation.PostConstruct;import cn.sh.ideal.manager.util.AESUtils; import com.alibaba.fastjson.JSONObject; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.session.Session; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service;import cn.sh.ideal.dao.RedisDao; import cn.sh.ideal.manager.model.ResourceMenu; import cn.sh.ideal.manager.model.Role; import cn.sh.ideal.manager.model.User; import cn.sh.ideal.manager.service.SystemService; import cn.sh.ideal.manager.util.Constant; import cn.sh.ideal.manager.util.Encodes; import cn.sh.ideal.manager.util.UserUtil;/*** SystemAuthorizingRealm* 系統安全認證實現類** @author Genghc* @date 2015/7/8*/ @Service("systemAuthorizingRealm") public class SystemAuthorizingRealm extends AuthorizingRealm {private Logger logger = LoggerFactory.getLogger(getClass());/*加密方式*/public static final String HASH_ALGORITHM = "SHA-1";public static final int HASH_INTERATIONS = 1024;@Value("#{config['multiAccountLogin']}")private String multiAccountLogin;@Autowiredprivate SystemService systemService;@Autowiredprivate RedisDao redisDao;/*** 認證回調,登錄時調用** @param authenticationToken* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {SystemUsernamePasswordToken token = (SystemUsernamePasswordToken) authenticationToken;//獲取所有活動的會話數量int activeSessionSize = systemService.getActiveSessions(false).size();logger.info("login submit, active session size: {}, username: {}", activeSessionSize, token.getUsername());String username = token.getUsername();if(redisDao.readValue("PWD_ERROR_LOCK" + username) != null){throw new AuthenticationException("密碼連續輸入錯誤超過3次,帳號鎖定5分鐘,請和租戶管理員聯系");}//根據用戶名獲取用戶信息User user = systemService.getUserByLoginName(username);//校驗用戶名if (user != null) {if (Constant.NO.equals(user.getStatus())) {throw new AuthenticationException("msg:該已帳號禁止登錄.");}if(!AESUtils.aesEncrypt(String.valueOf(token.getPassword())).equals(user.getPassword())){AuthenticationException ae = null;String errorMsg = "密碼錯誤!";/** 密碼輸錯三次鎖定開始 **/if(redisDao.readValue("PWD_ERROR_" + username) == null){redisDao.saveValue("PWD_ERROR_" + username, 1,2,TimeUnit.MINUTES);ae = new AuthenticationException("密碼錯誤,還能輸入2次");}else{Integer errorNum = (Integer) redisDao.readValue("PWD_ERROR_" + username);if(errorNum.intValue()>=2){redisDao.saveValue("PWD_ERROR_LOCK" + username, "PWD_ERROR_LOCK", 3, TimeUnit.MINUTES);redisDao.deleteValue("PWD_ERROR_" + username);ae = new AuthenticationException("密碼連續輸入錯誤超過3次,帳號鎖定3分鐘,請和租戶管理員聯系");}else{redisDao.saveValue("PWD_ERROR_" + username, errorNum.intValue() + 1,2,TimeUnit.MINUTES);ae = new AuthenticationException("密碼錯誤,還能輸入1次");}}/** 密碼輸錯三次鎖定結束 **/throw ae;}else{if(redisDao.exist("PWD_ERROR_" + username))redisDao.deleteValue("PWD_ERROR_" + username);}UserUtil.getSession().setAttribute("tenantCode",user.getTenantCode());UserUtil.getSession().setAttribute("username",user.getUserAccount());SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(new Principal(user), user.getPassword(),null, getName());logger.info("simpleAuthenticationInfo:{}",simpleAuthenticationInfo.getCredentials());return simpleAuthenticationInfo;} else {throw new AuthenticationException("帳號不存在,請和租戶管理員聯系"); // return null;}}/*** 授權查詢回調函數, 進行鑒權但緩存中無用戶的授權信息時調用** @param principalCollection* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {Principal principal = (Principal) getAvailablePrincipal(principalCollection);// 是否允許多處登錄if (!Constant.TRUE.equals(multiAccountLogin)) {Collection<Session> sessions = systemService.getActiveSessions(true, principal, UserUtil.getSession());if (sessions.size() > 0) {// 如果是登錄進來的,則踢出已在線用戶if (UserUtil.getSubject().isAuthenticated()) {for (Session session : sessions) {systemService.deleteSession(session);}}// 記住我進來的,并且當前用戶已登錄,則退出當前用戶提示信息。else {UserUtil.getSubject().logout();throw new AuthenticationException("msg:賬號已在其它地方登錄,請重新登錄。");}}}User user = systemService.getUserByLoginName(principal.getLoginName());if (user != null) {SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();List<ResourceMenu> list = systemService.getMenuList(user.getId());logger.info("驗證權限:" + JSONObject.toJSONString(list));for (ResourceMenu menu : list) {if (StringUtils.isNotBlank(menu.getPermission())) {// 添加基于Permission的權限信息for (String permission : StringUtils.split(menu.getPermission(), ",")) {info.addStringPermission(permission);}}}UserUtil.getSession().setAttribute("menuList",list);// 添加用戶權限// info.addStringPermission("user");List<Role> roleList = systemService.getRoleList(user.getId());if (roleList != null) {// 添加用戶角色信息for (Role role : roleList) {info.addRole(role.getRoleName());}}// 更新登錄IP和時間// getSystemService().updateUserLoginInfo(user);// 記錄登錄日志// LogUtils.saveLog(Servlets.getRequest(), "系統登錄");return info;} else {return null;}}/*** 設定密碼校驗的Hash算法與迭代次數*/@PostConstructpublic void initCredentialsMatcher() {/* HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(HASH_ALGORITHM);matcher.setHashIterations(HASH_INTERATIONS);matcher.setStoredCredentialsHexEncoded(true);*/setAuthenticationTokenClass(AuthenticationToken.class);setCredentialsMatcher(new CustomCredentialsMatcher());}/*** 授權用戶信息*/public static class Principal implements Serializable {private static final long serialVersionUID = 1L;private String id; // 編號private String loginName; // 登錄名private String name; // 姓名private String tenantCode;// private Map<String, Object> cacheMap;public Principal(User user) {this.id = user.getId();this.loginName = user.getUserAccount();this.name = user.getName();this.tenantCode = user.getTenantCode();}public String getId() {return id;}public String getLoginName() {return loginName;}public String getName() {return name;}public String getTenantCode() {return tenantCode;}/*** 獲取SESSIONID*/public String getSessionid() {try {return "";} catch (Exception e) {return "";}}@Overridepublic String toString() {return id;}} } 與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的Shrio 自定义算法登录认证的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。