spring集成shiro实现登录认证自定义验证功能(认证采用国密SM4算法)

13 篇文章 0 订阅
10 篇文章 0 订阅

        公司在建项目采用的开发框架为spring+springMvc+hibernate,安全框架采用的是shiro,安全认证沿用了shiro自带的HashedCredentialsMatcher,现客户(国企)要求用户密码必须采用国密SM4算法进行加密,因此需对安全认证模块进行改造。

SM4加密JAVA版可参考:http://blog.csdn.net/lemon_tree12138/article/details/42678723

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算法加密保存数据,可以进行系统登录测试了!

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值