Shiro 보안 프레임 워크의 소개 및 구성 세부 사항

소개:

Shiro는 apache의 오픈 소스 보안 프레임 워크로 , 사용자 인증, 권한, 권한 부여 , 암호화, 세션 관리 및 기타 기능 을 달성하기 위해 보안 인증 소프트웨어 시스템 관련 기능을 끌어내어 공통 보안 인증 프레임 워크를 형성하고 shiro를 사용하여 개발을 완료 할 수 있습니다. 인증, 권한 부여 및 기타 기능을 매우 빠르게 처리하여 시스템 비용을 절감합니다.

요약 구조 :

자세한 구조 :

첫 번째 레이어 : 주제 

두 번째 계층 : securiryManager-   관리 구성 요소 작업을 조정하는 데 사용되는 Shiro의 핵심

인증 자 : 인증 관리자-  인증 작업 수행을 담당합니다.

권한 부 여자 : 권한 부여 관리자-  권한 감지 담당

세션 관리 :

세 번째 계층 : 영역-영역은 shiro와 애플리케이션 보안 데이터를 연결하는 다리입니다.

실제 전투 :

配置Shiro安全过滤器

WEB-INF / web.xml

  <!-- 配置Shiro安全过滤器 -->
  <filter>
		<filter-name>DelegatingFilterProxy</filter-name>
		<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
		<!-- 初始化参数 -->
		<init-param>
			<param-name>targetBeanName</param-name>
			<param-value>shiroFilter</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>DelegatingFilterProxy</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

spring-configs.xml

    <!-shiro 프레임 워크 구성->
    
    <!- 영역 개체 구성 (봄에 의해 관리 됨)->
    <bean id = "userRealm" 
            class = "com.jt.sys.service.realm.ShiroUserRealm">
        <!-Credential matcher (암호 암호화)->
        <property name = "credentialsMatcher">
            <bean class = "org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                <property name = "hashAlgorithmName"value = "MD5 "/>
                <!-<property name ="hashIterations "value ="1024 "/>->
            </ bean>
        </ property>
    </ bean>
    <!-CacheManager 개체를 구성합니다. 성능 향상,인증 정보 및 권한 부여 정보는 캐시 될 수 있습니다.)->
    <bean id = "cacheManager"class = "org.apache.shiro.cache.ehcache.EhCacheManager">
        <!-이미있는 경우 여기에서 net.sf.ehcache.CacheManager 인스턴스를 설정합니다. 그렇지 않은 경우
             기본 구성 으로 새 구성이 생성됩니다.
             <property name = "cacheManager"ref = "ehCacheManager"/>->
        <!-사전 빌드 된 net.sf.ehcache가없는 경우 .CacheManager 인스턴스를 주입하지만
             특정 Ehcache 구성을 사용하려면 여기에서 지정하십시오. 그렇지 않으면 기본값
             이 사용됩니다. :->
        <property name = "cacheManagerConfigFile"value = "classpath : ehcache.xml"/> 
    </ bean>
    <!-配置securityManager 对象(此 对象 时 shiro框架 核心)->
    <bean id = " 
       class = "org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name = "realm"ref = "userRealm"/> 
        <property name = "cacheManager"ref = "cacheManager"/>  
    </ bean>
    <! - (자원 요청, 인증 될 릴리스 요청 필터링이 필터 장치를 통해 달성) 구성 shiroFilter > -
    <빈 ID = "shiroFilter"클래스 = "org.apache.shiro.spring.web.ShiroFilterFactoryBean을 ">
         <!-shiro의 핵심 보안 인터페이스->
         <property name ="securityManager "ref ="securityManager "/>
         <!- 로그인시 연결 필요 ->
         <property name ="loginUrl "값 = "/loginUI.do"> </ property>
         <!-성공적인 로그인 후 점프 할 연결 (로그인에서 처리됨)->
         <!-<property name = "successUrl"value = "/ index.jsp"> </ property>-- >
         <!-권한이없는 리소스에 액세스 할 때 점프 연결 
         <property name = "unauthorizedUrl"value = "/ default.html"> </ property>->
         <!-shiro 연결 제약 구성-->
         <property name = "filterChainDefinitions">
             <value>
                 <!-정적 리소스 설정에 대한 익명 액세스 허용->
                 / bower_components / ** = anon
                 / build / ** = anon
                 / dist / ** = anon
                 / plugins / ** = anon
                 /doLogin.do = anon
                 <!-
                 Exit- > /doLogout.do = logout <!-주제의 로그 아웃 메서드가 호출되고이 메서드는 세션을 지 웁니다->
                 <!                  - 나머지 다른 경로는 액세스하기 전에 인증되어야합니다 .->
/ ** = authc
             </ value>
         </ property>
     </ bean>
     
    <!-Shiro 生命 周期 处理器->
    <bean id = "lifecycleBeanPostProcessor" 
    class = "org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
    
    <!-启用 shiro 注解 权限 检查 (@RequestPermissions)->
    <bean class = "org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
        depends-on = "lifecycleBeanPostProcessor"/>
    <bean class = "org.apache.shiro.spring .security.interceptor.AuthorizationAttributeSourceAdvisor ">
        <property name ="securityManager " 
                  ref ="securityManager "/>
    </ bean>

 

인증:

인증 과정 :

 

  1. 시스템은 사용자 정보 토큰을 SecurityManager에 제출하기 위해 subject의 로그인 메소드를 호출합니다.

          subject.login (토큰)

        // 이 요청은 SecurityManager에 제출됩니다.

        // SecurityManager 는 인증 프로세서 Authenticator를 호출합니다.

        // 인증 프로세서는 인증 정보를 얻기 위해 관련 Realm 객체에 액세스합니다.

  1. SecurityManager는 인증 작업을 인증 자 개체 Authenticator에 위임합니다.
  2. 인증자는 ID 정보를 Realm에 전달합니다.

SysUser sysUser = sysUserDao.findUserByUserName (사용자 이름);

  1. Realm은 데이터베이스에 접근하여 사용자 정보를 얻은 다음 정보를 캡슐화하고 반환합니다.

        //3.2 사용자 정보 캡슐화

        AuthenticationInfo 정보

        = new SimpleAuthenticationInfo (

                sysUser.getUsername (), // 마스터 ID

                sysUser.getPassword (), // 암호화 된 암호

                byteSource, // 솔트에 해당하는 바이트 소스 객체

                getName ()); // realm 의 이름

5) 인증자는 영역에서 반환 된 정보를 인증합니다.

 

 

SysLoginController.java

@Controller
@RequestMapping("/")
public class SysLoginController {
	  @Autowired
      private SysUserService sysUserService;
	  @RequestMapping("loginUI")
	  public String loginUI(){
		  return "login";
	  }
	  @RequestMapping("doLogin")
	  @ResponseBody
	  public JsonResult doLogin(String username, String password){
		  String r=DigestUtils.md5DigestAsHex("123456".getBytes());
		  System.out.println("r="+r);
		    sysUserService.login(username, password);
		  return new JsonResult("login ok");
	  }
}

 

@Service
public class SysUserServiceImpl implements SysUserService {
	
	@Autowired
	private SysUserDao sysUserDao;
	@Autowired
	private SysRoleDao sysRoleDao;
	@Autowired
	private SysUserRoleDao sysUserRoleDao;
	
	@Override
	public void login(String username,String password) {
		System.out.println("service.login");
		//0.参数合法性验证
		if(StringUtils.isEmpty(username))
		throw new ServiceException("用户名不能为空");
		if(StringUtils.isEmpty(password))
		throw new ServiceException("密码不能为空");
		//1.获取Subject(主体)对象
		Subject subject=SecurityUtils.getSubject();
		//2.封装用户名和密码
		UsernamePasswordToken token=new UsernamePasswordToken(username, password);
	    //3.执行身份认证
		try {
		subject.login(token);
		//此请求会提交给SecurityManager
		//SecurityManager会调用认证处理器Authenticator
		//认证处理器会去访问相关Realm对象获取认证信息
		} catch (AuthenticationException e) {
		e.printStackTrace();
		throw new ServiceException("用户名或密码不正确");
		}
		//4.记录用户信息
		Session session=
		SecurityUtils.getSubject().getSession();
	    session.setAttribute("user", username);
	}

AuthorizingRealm 상속 doGetAuthenticationInfo 재정의

Realm을 통한 기본 인증 및 권한 제어 실현

public class ShiroUserRealm extends AuthorizingRealm {

	@Autowired
	private SysUserDao sysUserDao;

	/**
	 * 完成认证信息的获取以及封装
	 * 此方法何时调用?(执行登陆认证时调用)
	 * @param  
	 * 用于接收用户身份以及凭证信息的对象(用户输入的)
	 * 
	 * @return AuthenticationInfo  
	 * 封装了认证信息的对象(从数据库查询到的)
	 * 
	 * client-->controller-->service-->realm
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		System.out.println("realm.doGetAuthenticationInfo");
		//1.获取用户身份信息
		UsernamePasswordToken uToken= 	(UsernamePasswordToken)token;
		String username=uToken.getUsername();
		//2.基于用户身份查询数据库信息
		SysUser sysUser=
		sysUserDao.findUserByUserName(username);
		//3.对查询结果进行封装.
		//3.1获取用户salt值,并将其转换为一个字节源对象
		ByteSource byteSource= ByteSource.Util.bytes(sysUser.getSalt());
		//3.2对用户信息进行封装返回.
		AuthenticationInfo info=
		new SimpleAuthenticationInfo(
		sysUser.getUsername(), //主身份
		    sysUser.getPassword(), //已加密的密码
		    byteSource,//salt对应的字节源对象
		    getName());//realm 的名字
		return info;
	}
}

 

public interface SysUserDao {
	/**
	 * 根据用户名查找用户信息
	 * @param username
	 * @return
	 */
	SysUser findUserByUserName(String username);
}

 

     <select id="findUserByUserName" resultType="sysUser">
           select *  from sys_users
           where username=#{username}        
     </select>

승인 구현 :

방법:

  1. 시스템은 주제 관련 메소드 isPermitted를 호출하여 리소스 / hasRole을 기반으로 사용자 정보를 SecurityManager 에 제출합니다.

2) SecurityManager는 권한 감지 작업을 Authorizer 개체위임합니다.

3) 권한 부여자는 사용자 정보를 영역에 위임합니다

 List <문자열> 목록 = sysUserDao.findUserPermissions (사용자 이름);

  1. Realm은 데이터베이스에 액세스하여 사용자 권한 정보를 얻고이를 캡슐화합니다 .

SimpleAuthorizationInfo info = new SimpleAuthorizationInfo ();

info.setStringPermissions (permissions);

  1. 인증자는 사용자 인증 정보를 판단합니다.

@RequiresPermissions ( "sys : user : update")

 

    @RequestMapping("doDeleteObject")
    @ResponseBody
    public JsonResult doDeleteObject(String idStr){
    	sysRoleService.deleteObject(idStr);
    	return new JsonResult();
    }

 

	@RequiresPermissions("sys:role:delete")
	@Override
	public int deleteObject(String idStr) {
		//1.参数合法性验证
		if(StringUtils.isEmpty(idStr))
		throw new ServiceException("必须选中才能删除");
		//2.解析字符串
		String[] ids=idStr.split(",");
		//3.调用数据层方法执行删除操作
		int rows=sysRoleDao.deleteObject(ids);
		
		for(String id:ids){
			sysRoleMenuDao.deleteObject(Integer.valueOf(id));
		    sysUserRoleDao.deleteObject(null, Integer.valueOf(id));
		}
		//4.返回处理结果
		if(rows==0)
		throw new ServiceException("数据已经不存在");
		return rows;
	}

Realm을 통한 기본 인증 및 권한 제어 실현

public class ShiroUserRealm extends AuthorizingRealm {
	
	@Autowired
	private SysUserDao sysUserDao;
	/***
	 * 完成授权信息的获取以及封装.
	 * 此方法何时调用?(执行授权检测时调用)
	 * 
	 */
	@Override
	protected AuthorizationInfo 
	doGetAuthorizationInfo(
			PrincipalCollection principals) {
		System.out.println("realm.doGetAuthorizationInfo");
		//1.获取登陆用户身份信息
		String username=
		(String)principals.getPrimaryPrincipal();
		//2.查找用户的权限信息
		List<String> list=//sys:user:update,sys:user:view,....,
		sysUserDao.findUserPermissions(username);
		System.out.println("list="+list);
		Set<String> permissions=new HashSet<>();
		for(String permission:list){
			if(!StringUtils.isEmpty(permission)){
				permissions.add(permission);
			}
		}
		
		System.out.println("set="+permissions);
		//3.对权限信息进行封装
		SimpleAuthorizationInfo info=
		new SimpleAuthorizationInfo();
		info.setStringPermissions(permissions);
		return info;
	}

 

	/**
	 * 根据用户id查找用户权限标识信息
	 * 例如:sys:role:view,sys:role:add
	 * @param userId
	 * @return
	 */
	List<String> findUserPermissions(String username);

 

     <select id="findUserPermissions"
             resultType="string">
           select m.permission
           from sys_users u join 
                sys_user_roles ur join 
                sys_role_menus rm join 
                sys_menus m
                
                on u.id=ur.user_id   and 
                ur.role_id=rm.role_id  and 
                rm.menu_id=m.id 
           where u.username=#{username}
     </select>
 <!-- 整合Shiro 安全框架-->
 
  <dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-spring</artifactId>
   <version>1.3.2</version>
  </dependency>

 

관련 테이블 :

sys_roles

sys_users

sys_menus

sys_role_menus

sys_user_roles

CREATE TABLE `sys_roles` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL COMMENT '角色名称',
  `note` varchar(500) DEFAULT NULL COMMENT '备注',
  `createdTime` datetime DEFAULT NULL COMMENT '创建时间',
  `modifiedTime` datetime DEFAULT NULL COMMENT '修改时间',
  `createdUser` varchar(20) DEFAULT NULL COMMENT '创建用户',
  `modifiedUser` varchar(20) DEFAULT NULL COMMENT '修改用户',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=45 DEFAULT CHARSET=utf8 COMMENT='角色';
CREATE TABLE `sys_users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `password` varchar(100) DEFAULT NULL COMMENT '密码',
  `salt` varchar(50) DEFAULT NULL COMMENT '盐  密码加密时前缀,使加密后的值不同',
  `email` varchar(100) DEFAULT NULL COMMENT '邮箱',
  `mobile` varchar(100) DEFAULT NULL COMMENT '手机号',
  `valid` tinyint(4) DEFAULT NULL COMMENT '状态  0:禁用   1:正常  默认值 :1',
  `createdTime` datetime DEFAULT NULL COMMENT '创建时间',
  `modifiedTime` datetime DEFAULT NULL COMMENT '修改时间',
  `createdUser` varchar(20) DEFAULT NULL COMMENT '创建用户',
  `modifiedUser` varchar(20) DEFAULT NULL COMMENT '修改用户',
  PRIMARY KEY (`id`),
  UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 COMMENT='系统用户';
CREATE TABLE `sys_menus` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL COMMENT '资源名称',
  `url` varchar(200) DEFAULT NULL COMMENT '资源URL',
  `type` int(11) DEFAULT NULL COMMENT '类型     1:菜单   2:按钮',
  `sort` int(11) DEFAULT NULL COMMENT '排序',
  `note` varchar(100) DEFAULT NULL COMMENT '备注',
  `parentId` int(11) DEFAULT NULL COMMENT '父菜单ID,一级菜单为0',
  `permission` varchar(500) DEFAULT NULL COMMENT '授权(如:user:create)',
  `createdTime` datetime DEFAULT NULL COMMENT '创建时间',
  `modifiedTime` datetime DEFAULT NULL COMMENT '修改时间',
  `createdUser` varchar(20) DEFAULT NULL COMMENT '创建用户',
  `modifiedUser` varchar(20) DEFAULT NULL COMMENT '修改用户',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=141 DEFAULT CHARSET=utf8 COMMENT='资源管理';
CREATE TABLE `sys_role_menus` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `role_id` int(11) DEFAULT NULL COMMENT '角色ID',
  `menu_id` int(11) DEFAULT NULL COMMENT 'ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1218 DEFAULT CHARSET=utf8 COMMENT='角色与菜单对应关系';
CREATE TABLE `sys_user_roles` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL COMMENT '用户ID',
  `role_id` int(11) DEFAULT NULL COMMENT '角色ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8 COMMENT='用户与角色对应关系';
INSERT INTO `jt_sys`.`sys_users`(`id`, `username`, `password`, `salt`, `email`, `mobile`, `valid`, `createdTime`, `modifiedTime`, `createdUser`, `modifiedUser`) VALUES (1, 'admin', '4ebd394fbd25e495e0753a7dc9889a8e', '7adb778c-e7d3-4dd3-a3c5-5f80a158006d', '[email protected]', '13624356789', 1, NULL, '2018-01-13 02:06:45', NULL, 'admin');
 
INSERT INTO `jt_sys`.`sys_menus`(`id`, `name`, `url`, `type`, `sort`, `note`, `parentId`, `permission`, `createdTime`, `modifiedTime`, `createdUser`, `modifiedUser`) VALUES (45, '用户管理', 'user/listUI.do', 1, 45, NULL, 8, 'sys:user:view', '2017-07-12 15:15:59', '2017-07-21 17:36:01', 'admin', 'admin');
 

 

추천

출처blog.csdn.net/qq_24271537/article/details/109324820