springboot+shiro

SSS+Shiro配置

本文主要概述sss+shiro的配置,其他业务层,持久层方法自行书写。采用SpringBoot快速构建项目,其他Spring、SpringMvc、SpringDataJpa的配置不予叙述。其中ShiroConfig.java、ShiroTagFreemarker.java为配置类放在resources下,角色和权限需添加获取所有角色名和权限名的两个方法,返回为Set<String>

1、 Pom.xml导入相关Jar包

<properties>
<commons-logging.version>1.2</commons-logging.versio>
		<shiro-all.version>1.2.5</shiro-all.version>
<slf4j-log4j12.version>1.7.25</slf4j-log4j12.versi>
</properties>
<!-- shiro 相关jar包 -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-all</artifactId>
			<version>${shiro-all.version}</version>
		</dependency>
<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>${commons-logging.version}</version>
		</dependency>
		<dependency>
			<groupId>net.mingsoft</groupId>
			<artifactId>shiro-freemarker-tags</artifactId>
			<version>1.0.0</version>
		</dependency>
		<!-- slf4j -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
		</dependency>

2、 编写MyRealm.java

package com.gezhi.telecom.realm;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.Resource;

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.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import com.gezhi.telecom.adminmag.service.IAdminService;
import com.gezhi.telecom.bean.AccountBean;
import com.gezhi.telecom.bean.AdministratorBean;
import com.gezhi.telecom.bean.RoleBean;
import com.gezhi.telecom.rolepermismag.permissionmag.service.IPermissionService;
import com.gezhi.telecom.rolepermismag.rolemag.service.IRoleService;
import com.gezhi.telecom.usermag.accountingmag.service.IAccountingService;
/**
 * 数据源realm
 * @author Administrator
 *
 */
public class DataBaseRealm extends AuthorizingRealm {
	@Resource
	private IAdminService adminServiceImpl;
	@Resource
	private IAccountingService accountingServiceImpl;
	@Resource
	private IRoleService roleServiceImpl;
	@Resource
	private IPermissionService permissionServiceImpl;
//授权	
@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
		// TODO Auto-generated method stub
		// 能进入到这里,表示账号已经通过验证了
				String name = (String) arg0.getPrimaryPrincipal();
				AdministratorBean admin=adminServiceImpl.findAdminByAccount(name);
				Set<String> roles = new HashSet<>();
				RoleBean role=null;
				if(admin!=null) {
					 role=roleServiceImpl.findRoleBeanById(admin.getRole().getId());
				}else {
					AccountBean account=accountingServiceImpl.findAccountBeanByAccount(name);
					if(account!=null) {
						role=roleServiceImpl.findRoleBeanById(account.getRole().getId());
					}
				}
				// 获取账号的角色和权限信息(请在业务层书写获取权限名和角色名的方法,返回都为Set<String>)
				roles.add(role.getRoleName());
				
				List permission=permissionServiceImpl.findPermissionNameByRoleId(role.getId());
				Set<String> permissions = new HashSet<>(permission);
				System.out.println(permissions);
				// 授权对象信息
				SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
				authorizationInfo.setStringPermissions(permissions);
				authorizationInfo.setRoles(roles);
				return authorizationInfo;
	}

//验证	
@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
		// TODO Auto-generated method stub
		UsernamePasswordToken upToken = (UsernamePasswordToken) arg0;
		String name = upToken.getPrincipal().toString();

		// 获取指定用户数据库中的密码,盐
		AdministratorBean admin=adminServiceImpl.findAdminByAccount(name);
		String pwdInDB="";
		String salt="";
		if(admin!=null) {
			pwdInDB = admin.getPassword();
			salt = admin.getPasswordSalt();
		}else {
			AccountBean account=accountingServiceImpl.findAccountBeanByAccount(name);
			if(account!=null) {
				pwdInDB = account.getPassword();
				salt = account.getSalt();
			}
		}
		// 认证信息,存放账号,密码,盐,getName() 是当前 Realm 的继承方法,通常返回当前类名 :databaseRealm
		// 通过 applicationContext-shiro.xml 里配置的 HashedCredentialsMatcher 进行自动校验
		SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
				name,pwdInDB, ByteSource.Util.bytes(salt),getName());
		return authenticationInfo;
	}


}

3、 书写配置类ShiroConfig.java

package com.gezhi.telecom.config;

import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import com.gezhi.telecom.realm.DataBaseRealm;
/**
 * 
 * @author Administrator
 *
 */
@Configuration
public class ShiroConfig {
	@Bean
	public ShiroFilterFactoryBean shirFilter(org.apache.shiro.mgt.SecurityManager securityManager) {
		System.out.println("ShiroConfiguration.shirFilter()");
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		//拦截器.
		Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
		// 配置不会被拦截的链接 顺序判断
		filterChainDefinitionMap.put("/static/**", "anon");
		filterChainDefinitionMap.put("/system/login", "anon");
		//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
		filterChainDefinitionMap.put("/logout", "logout");
		//<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
		//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
		filterChainDefinitionMap.put("/**", "authc");
		// 如果不设置默认会自动寻找Web工程根目录下的"/login.ftl"页面
    	shiroFilterFactoryBean.setLoginUrl("/sys/login");
		// 登录成功后要跳转的链接
	   shiroFilterFactoryBean.setSuccessUrl("/index");
	  

		//未授权界面;
//		shiroFilterFactoryBean.setUnauthorizedUrl("/403");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return shiroFilterFactoryBean;
	}

	@Bean
	public DataBaseRealm myShiroRealm(){
		DataBaseRealm myShiroRealm = new DataBaseRealm();
		return myShiroRealm;
	}


//    /**
//     * 凭证匹配器
//     * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
//     * )
//     *
//     * @return
//     */
//    @Bean
//    public HashedCredentialsMatcher hashedCredentialsMatcher() {
//        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//        hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
//        hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5(""));
//        return hashedCredentialsMatcher;
//
//     }
    
    @Bean
	public DefaultWebSecurityManager securityManager(){
		DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
		securityManager.setRealm(myShiroRealm());
		return securityManager;
	}
}
**

4、 编写密码加密工具类

package com.gezhi.telecom.util;

import org.apache.shiro.crypto.hash.SimpleHash;

import com.gezhi.telecom.bean.AccountBean;
import com.gezhi.telecom.bean.AdministratorBean;
/**
 * 密码加密工具类
 * @author Administrator
 *
 */
public class PasswordEncryptionUtil {
	/**
	 * 加密
	 * @param algorithmName 加密算法名称
	 * @param hashIterations 迭代次数
	 * @param user 加密对象
	 * @return 加密后的对象
	 */
	public static Object AllPasswordEncryption(String algorithmName,int hashIterations,Object obj) {
		String salt = "cjwdzkyxz";	// 盐值
		if(obj instanceof AdministratorBean) {
			AdministratorBean admin=(AdministratorBean) obj;
			//获得用户输入的密码
			String password=admin.getPassword();
			//通过SimpleHash使用散列算法和盐值得到最终加密密码
			String encodePassword=new SimpleHash(algorithmName, password, salt, hashIterations).toString();
			admin.setPassword(encodePassword);
			admin.setPasswordSalt(salt);
			return admin;
		}else {
			AccountBean account=(AccountBean) obj;
			String password=account.getPassword();
			//通过SimpleHash使用散列算法和盐值得到最终加密密码
			String encodePassword=new SimpleHash(algorithmName, password, salt, hashIterations).toString();
			account.setPassword(encodePassword);
			account.setSalt(salt);
			return account;
			
		}
		
		
	}
}
**

5、 在Controller使用密码加密

	@ResponseBody
	@RequestMapping(value = "/{id}", method = RequestMethod.POST, produces = "application/json;charset=utf-8")
	public ResMessage saveAccountBean(AccountBean accoun) {
		
		ResMessage res = new ResMessage(true, "操作成功!");
		try {			
			accoun.setId(null);
			accoun.setCreateTime(new Date());
			PasswordEncryptionUtil.AllPasswordEncryption("md5", 2, accoun);//调用密码加密工具类
			AccountingServiceImpl.addAccounting(accoun);			
		} catch (Exception e) {
			// TODO: handle exception
			res.setStatus(false);
			res.setInfo("系统繁忙,请稍后重试!");
		}
		return res;		
	}

6、 编写登录Controller

package com.gezhi.telecom.rolepermismag.controller;

import javax.annotation.Resource;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.gezhi.telecom.adminmag.service.IAdminService;
import com.gezhi.telecom.bean.AccountBean;
import com.gezhi.telecom.bean.AdministratorBean;
import com.gezhi.telecom.usermag.accountingmag.service.IAccountingService;

@RequestMapping("/system")
@Controller
public class LoginController {
	@Resource
	private IAccountingService accountingServiceImpl;
	@Resource
	private IAdminService adminServiceImpl;

	/**
	 * 登录,获取账号密码进行验证
	 */
	@RequestMapping(value = "/login", method = RequestMethod.POST)
	public String login(Model model, String username, String password) {
		Subject subject = SecurityUtils.getSubject();//获得当前用户对象
		String salt = "cjwdzkyxz";	// 盐值
		String encodePassword=new SimpleHash("md5", password, salt, 2).toString();//加密密码
		UsernamePasswordToken token = new UsernamePasswordToken(username, encodePassword);
		try {
			subject.login(token);
			Session session = subject.getSession();
			String userName=(String) subject.getPrincipal();
			System.out.println("欢迎登录!");
			session.setAttribute("subject", subject);
			session.setAttribute("userName", userName);
			AccountBean acc=accountingServiceImpl.findAccountBeanByAccount(userName);
			Byte by;
			if(acc!=null) {
			by=acc.getRole().getRoleByte();
			}else {
				AdministratorBean admin=adminServiceImpl.findAdminByAccount(userName);
				System.out.println(admin);
				by=admin.getRole().getRoleByte();	
			}
			String roleType="";
			if(by==0) {
				roleType="超级管理员";
			}else if(by==1) {
				roleType="普通管理员";
			}else {
				roleType="用户";
			}
			session.setAttribute("roleType", roleType);
			return "/index";
		}catch(UnknownAccountException e) {
	         System.out.println("用户名或密码错误");
	         return "/login";
         }catch(IncorrectCredentialsException e) {
	        System.out.println("用户名或密码错误");
	        return "/login";
         }
//			model.addAttribute("error", "验证失败");
		
		
	}
/**
 * 退出
 * @param model
 * @param username
 * @param password
 * @return
 */
	@RequestMapping(value = "/loginout", method = RequestMethod.GET)
	public String loginOut(Model model, String username, String password) {
		Subject subject = SecurityUtils.getSubject();
		subject.logout();
		return "/login";

	}

}

7、 编写ShiroTagFreemarker.java ftl引入shiro标签

package com.gezhi.telecom.config;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import com.jagregory.shiro.freemarker.ShiroTags;

import freemarker.template.TemplateModelException;
/**
 * 用于ftl引入shiro标签
 * @author Administrator
 *
 */
@Configuration
public class ShiroTagFreemarkerConfig {
	  @Resource
	    private FreeMarkerConfigurer freeMarkerConfigurer;

	    @PostConstruct
	    public void setSharedVariable() throws TemplateModelException {
	        freeMarkerConfigurer.getConfiguration().setSharedVariable("shiro", new ShiroTags());
	    }
}

8、 使用<@shiro.hasPermission name=“用户管理”></@shiro.hasPermission> 标签判断是否拥有权限

<@shiro.hasPermission name="用户管理">
<dl id="menu-product">
	<dt><i class="Hui-iconfont">&#xe620;</i> 用户管理系统<i class="Hui-iconfont menu_dropdown-arrow">&#xe6d5;</i></dt>
	<dd>
		<ul>
			<li><a data-href="administratorAccount.html" data-title="管理员管理" href="javascript:void(0)">管理员管理</a></li>
			<li><a data-href="businessAccount.html" data-title="业务账号管理" href="javascript:void(0)">业务账号管理</a></li>
			<li><a data-href="accountingAccount.html" data-title="账务账号管理" href="javascript:void(0)">账务账号管理</a></li>
	</ul>
</dd>
</dl>
</@shiro.hasPermission>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值