spring整合shiro實現登入認證自定義驗證功能(認證採用國密SM4演算法)
阿新 • • 發佈:2019-02-18
公司在建專案採用的開發框架為spring+springMvc+hibernate,安全框架採用的是shiro,安全認證沿用了shiro自帶的HashedCredentialsMatcher,現客戶(國企)要求使用者密碼必須採用國密SM4演算法進行加密,因此需對安全認證模組進行改造。
1、新建一個自定義的適用於SMA4安全認證匹配類:
public class SM4CredentialsMatcher extends SimpleCredentialsMatcher { protected UserService userService; @Override public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) { UsernamePasswordToken token = (UsernamePasswordToken) authcToken; User user = userService.findByLoginName(token.getUsername()); String salt = ""; if (user != null) { if ("disabled".equals(user.getStatus())) { throw new DisabledAccountException(); } salt = user.getSalt(); } Object tokenCredentials = SM4Util.encrypt(String.valueOf(token.getPassword()), salt); Object accountCredentials = getCredentials(info); // 將密碼加密與系統加密後的密碼校驗,內容一致就返回true,不一致就返回false return equals(tokenCredentials, accountCredentials); } public void setUserService(UserService userService) { this.userService = userService; } }
2、修改自定義Realm類,重寫兩個方法:initCredentialsMatcher和assertCredentialsMatch
public class ShiroDbRealm extends AuthorizingRealm { protected UserService userService; protected RoleService roleService; protected SM4CredentialsMatcher sm4CredentialsMatcher; /** * 認證回撥函式,登入時呼叫. */ @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken authcToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authcToken; User user = userService.findByLoginName(token.getUsername()); if (user != null) { if ("disabled".equals(user.getStatus())) { throw new DisabledAccountException(); } byte[] salt = Encodes.decodeHex(user.getSalt()); return new SimpleAuthenticationInfo(new ShiroUser( user.getLoginName(), user.getName(), user.getId()), user.getPassword(), ByteSource.Util.bytes(salt), getName()); } else { return null; } } /** * 授權查詢回撥函式, 進行鑑權但快取中無使用者的授權資訊時呼叫. */ @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal(); // User user = userService.findByLoginName(shiroUser.getLoginName()); List<Role> roles = this.userService .findRolesByUserId(shiroUser.getId()); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); for (Role role : roles) { // 基於Role的許可權資訊 info.addRole(role.getCode()); } info.addStringPermissions(this.userService .findUserPermissions(shiroUser.getId())); return info; } /** * 更新使用者授權資訊快取. */ public void clearCachedAuthorizationInfo(String principal) { SimplePrincipalCollection principals = new SimplePrincipalCollection( principal, getName()); clearCachedAuthorizationInfo(principals); } /** * 清除所有使用者授權資訊快取. */ public void clearAllCachedAuthorizationInfo() { Cache<Object, AuthorizationInfo> cache = getAuthorizationCache(); if (cache != null) { for (Object key : cache.keys()) { cache.remove(key); } } } @PostConstruct public void initCredentialsMatcher() { //註釋掉原來的匹配器程式碼 //HashedCredentialsMatcher matcher = new HashedCredentialsMatcher( // userService.HASH_ALGORITHM); // matcher.setHashIterations(userService.HASH_INTERATIONS); // setCredentialsMatcher(matcher); //設定自定義的安全認證匹配器,注意此處最好將匹配器採用注入的方式設定,若採用new的方式話,在匹配器中將無法使用spring視窗中的其他元件 setCredentialsMatcher(sm4CredentialsMatcher); } /** * 認證密碼匹配呼叫方法 * * @param authcToken * @param info * @throws AuthenticationException */ @Override protected void assertCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authcToken; super.assertCredentialsMatch(token, info); } public void setUserService(UserService userService) { this.userService = userService; } public void setSm4CredentialsMatcher(SM4CredentialsMatcher sm4CredentialsMatcher) { this.sm4CredentialsMatcher = sm4CredentialsMatcher; }
3、修改spring有關shiro的配置
<description>Shiro安全配置</description> <!-- 單realm配置 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="adminRealm" /> <property name="cacheManager" ref="shiroEhcacheManager" /> </bean> <bean id="adminRealm" class="cn.company.framwork.sys.service.ShiroDbRealm" depends-on="userRepository,roleRepository"> <property name="userService" ref="userService" /> <!-- 將“安全認證匹配器”注入自定義的Realm中,用於初始化安全認證匹配器 --> <property name="sm4CredentialsMatcher" ref="sm4CredentialsMatcher" /> </bean> <!-- 本次改造新增的 安全認證匹配器 --> <bean id="sm4CredentialsMatcher" class="cn.company.framwork.sys.service.SM4CredentialsMatcher" depends-on="userRepository"> <property name="userService" ref="userService" /> </bean>
4、改造完畢,剩下新建使用者時也採用國密SM4演算法加密儲存資料,可以進行系統登入測試了!