shiro再次学习

编辑器要配置好spring的插件。具体可以百度
首先配置spring的环境
web.xml下
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>


<!-- Bootstraps the root web application context before servlet initialization -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
此处是spring的配置
<servlet>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>


<!-- Map all requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>


此处是springmvc的配置
    <filter>
        <filter-name>shiroFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>


    <filter-mapping>
        <filter-name>shiroFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
此处是shiro的配置 !此处要等spring配置好之后再加入!




创建
applicationContext.xml  创建在src根目录下
用于做spring的配置
创建spring-servlet.xml  创建在web-inf下
<context:component-scan base-package="com.test.shiro"></context:component-scan>

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"></property>
<property name="suffix" value=".jsp"></property>
</bean>

<mvc:annotation-driven></mvc:annotation-driven>
<mvc:default-servlet-handler/>




这里是做springmvc用的 前端控制器 扫描的包 
新建这个路径
com.test.shiro
新建jsp文件 user.jsp
运行项目:http://localhost:8080/shiro/user.jsp
打开出现user.jsp正常说明SPRING的环境已经配置好了
------
------
接下来开始整合shiro
web.xml文件已经加入了
在applicationContex.xml(也就是SPING来管理的shiro)中写入
核心部分 权限管理  SecurityManager
 <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="cacheManager" ref="cacheManager"/> 缓存
------ 这里是整合后才需要的 先注释 不然报错
 <property name="authenticator" ref="authenticator"></property> <property name="realms"> <list> <ref bean="jdbcRealm"/> <ref bean="secondRealm"/> </list> </property> <property name="rememberMeManager.cookie.maxAge" value="10"></property>
------ 这里是整合后才需要的 先注释 不然报错
现在需要的配置是  :全部整合好了之后可以不用  <property name="realm" ref="jdbcRealm"></property>
</bean>




 1.配置缓存cacheManager

cacheManager采用企业的管理方式 使用ehcache 。这个是需要加入jar包的 还有一种直接引用ehcachemanager
然后配置XML文件后期才再给。直接拿来使用就行。 


   <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <!-- Set a net.sf.ehcache.CacheManager instance here if you already have one.  If not, a new one
             will be creaed with a default config:
             <property name="cacheManager" ref="ehCacheManager"/> -->
        <!-- If you don't have a pre-built net.sf.ehcache.CacheManager instance to inject, but you want
             a specific Ehcache configuration to be used, specify that here.  If you don't, a default
             will be used.: -->
        <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/> 
    </bean>
2.可以配置session 现在展示不用
3.实现realm
用接口的方式实现  
    <bean id="jdbcRealm" class="com.test.shiro.realms.ShiroRealm">
    <property name="credentialsMatcher">
    <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
    <property name="hashAlgorithmName" value="MD5"></property>
    <property name="hashIterations" value="1024"></property>
    </bean>
    </property>
    </bean>
java文件:
4.配置生命周期shiro
 <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
5.ioc容器可以使用shiro的注解(配置了4之后才会出现效果)

  <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>


6.配置shirofiter 这里和web.xml中是是对应的。
 <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <property name="loginUrl" value="/login.jsp"/>
        <property name="successUrl" value="/list.jsp"/>
        <property name="unauthorizedUrl" value="/unauthorized.jsp"/>
        
------ 这里是整合后才需要的 先注释 不然报错
 <property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"></property> 后期加上比较好的配置 
------ 这里是整合后才需要的 先注释 不然报错
<!-- 配置哪些页面需要受保护. 以及访问这些页面需要的权限. 

1). anon 可以被匿名访问 

2). authc 必须认证(即登录)后才可能访问的页面.

 3). logout 登出. 

4). roles 角色过滤器 -->

 <property name="filterChainDefinitions"> 

<value> /login.jsp = anon 

/shiro/login = anon 

/shiro/logout = logout 

/user.jsp = roles[user] 

/admin.jsp = roles[admin] 

# everything else requires authentication:

 /** = authc </value> </property> 

</bean>






-----运行。此时框架已经可以跑起来   下载地址:http://download.csdn.net/detail/u013354696/9864885




下面进行整合realm实现认证


/shiro/src/com/test/shiro/handler/ShiroHandler.java 新建控制器

大致的作用就是将表单接收到的用户密码封装起来。进行登录验证

记得要加上控制器的注解

@Controller
@RequestMapping("/shiro")
public class ShiroHandler {

	@RequestMapping("/login")
	public String login(@RequestParam("username") String username,
			@RequestParam("password") String password) {
		Subject subject = SecurityUtils.getSubject();
		if (!subject.isAuthenticated()) {
			UsernamePasswordToken token = new UsernamePasswordToken(username,
					password);
			token.setRememberMe(true);
			try {
				subject.login(token);
			} catch (AuthenticationException e) {
				System.out.println("登录失败" + e.getMessage());
			}
		}

		return "redirect:/list.jsp";

	}

}




 
 /shiro/src/com/test/shiro/realms/ShiroRealm.java  这个继承类之前就已经创建好。但是不用实现realm接口要改为继承AuthenticatingRealm

public class ShiroRealm extends AuthenticatingRealm {

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		System.out.println("doGetAuthenticationInfo"+token);
		return null;
	}

	

}


到此,可以运行项目会发现地址栏目的改变:

http://localhost:8080/shiro/login.jsp;jsessionid=BB3ACC73995EC9EE6AFB0FEC74DAC2D1

后面读了一个jsessionid的参数


输入了登录密码信息后,控制台会打印出

doGetAuthenticationInfo:org.apache.shiro.authc.UsernamePasswordToken - 456, rememberMe=true
登录失败Realm [com.test.shiro.realms.ShiroRealm@7c1e7] was unable to find account data for the submitted AuthenticationToken [org.apache.shiro.authc.UsernamePasswordToken - 456, rememberMe=true].

证明执行成功


接下来在次改写/shiro/src/com/test/shiro/realms/ShiroRealm.java

@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		// 1将AuthenticationToken转为usernamepasswordtoken
		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
		// 2获取usernamepasswordtoken 中的username
		String username = upToken.getUsername();
		// 3从数据库查询username的记录
		if ("unknown".equals(username)) {
			throw new UnknownAccountException("用户不存在");
		}

		//用户 密码 当前realm 直接用getName()
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username,
				"123456", getName());

		return info;
	}


其实就是做认证。用户名没有限定。密码123456 成功等会会进入跳转页面list.jsp

当然 也可以用AuthenticationToken  直接token.getPrincipal();强转一下获取当前用户信息这样就不需要 UsernamePasswordToken


开启加密MD5算法

web.xml里面的realm 改成这样


    <bean id="jdbcRealm" class="com.test.shiro.realms.ShiroRealm">
    	<property name="credentialsMatcher">
    		<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
    			<property name="hashAlgorithmName" value="MD5"></property>
    			<property name="hashIterations" value="1024"></property>
    		</bean>
    	</property>
    </bean>


	public static void main(String[] args) {
		Object re =new SimpleHash("MD5","123456" , null,1024);
		System.out.println(re);
	}

生成一个用MD5加密1024次 没有盐值的123456密码。

然后在替换到SimpleAuthenticationInfo 中的密码。就相当于这里已经执行了加密的算法


这里是最简单的实现

接下来是完整版本的实现

@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		// 1将AuthenticationToken转为usernamepasswordtoken
		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
		// // 2获取usernamepasswordtoken 中的username
		String username = upToken.getUsername();
		String mima = null;
		// String username = (String) token.getPrincipal();
		System.out.println("登录用户:" + username);
		// 3从数据库查询username的记录
		if ("unknown".equals(username)) {
			throw new UnknownAccountException("用户不存在");
		}

		if ("admin".equals(username)) {
			mima = "038bdaf98f2037b31f1e75b5b4c9b26e";
		} else if ("user".equals(username)) {
			mima = "098d2c478e9c11555ce2823231e02ec1";
		}

		ByteSource yan = ByteSource.Util.bytes(username);

		// 用户 密码 盐值 当前realm 直接用getName()
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username,
				mima, yan, getName());
		return info;
	}


----

以上完成了基本的加密和认证 还没有接入数据库的服务。全部都是静态的数据

----

接下来进行多realm的认证

场景的认证:  多个数据库源进行认证。需要多个realm实现不同的认证策略,比如密码的加密方式SHA1, MD5加密


/shiro/src/com/test/shiro/realms/SencondRealm.java


	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		// 1将AuthenticationToken转为usernamepasswordtoken
		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
		// // 2获取usernamepasswordtoken 中的username
		String username = upToken.getUsername();
		String mima = null;
		// String username = (String) token.getPrincipal();
		System.out.println("登录用户:" + username);
		// 3从数据库查询username的记录
		if ("unknown".equals(username)) {
			throw new UnknownAccountException("用户不存在");
		}

		if ("admin".equals(username)) {
			mima = "ce2f6417c7e1d32c1d81a797ee0b499f87c5de06";
		} else if ("user".equals(username)) {
			mima = "073d4c3ae812935f23cb3f2a71943f49e082a718";
		}

		ByteSource yan = ByteSource.Util.bytes(username);

		// 用户 密码 盐值 当前realm 直接用getName()
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username,
				mima, yan, getName());
		return info;
	}
	
	public static void main(String[] args) {
		Object re = new SimpleHash("SHA1", "123456",
				ByteSource.Util.bytes("user"), 1024);
		System.out.println(re);
	}


两个realm几乎是一样的,

在spring中配置realm

/shiro/src/applicationContext.xml加入

     <bean id="secondRealm" class="com.test.shiro.realms.SencondRealm">
    	<property name="credentialsMatcher">
    		<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
    			<property name="hashAlgorithmName" value="SHA1"></property>
    			<property name="hashIterations" value="1024"></property>
    		</bean>
    	</property>
    </bean> 

securityManager中的

    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="cacheManager" ref="cacheManager"/>
        <property name="authenticator" ref="authenticator"></property>
        <property name="realms">
        	<list>
    			<ref bean="jdbcRealm"/>
    			<ref bean="secondRealm"/>
    		</list>
        </property>    
<!--         <property name="rememberMeManager.cookie.maxAge" value="10"></property> -->
    </bean>

改为这个样子实现多realm

在配置一个认证器  具体可以去百度认证器策略。这里是所有的realm都认证


    <bean id="authenticator" 
    	class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
    	<property name="authenticationStrategy">
    		<bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>
    	</property>
    </bean>

也可以这样写 具体的策略可以自己决定

 <bean id="authenticator" 
    	class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
    	<!-- <property name="authenticationStrategy">
    		<bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>
    	</property> -->
    	<property name="realms">
    		<list>
    			<ref bean="jdbcRealm"/>
    			<ref bean="secondRealm"/>
    		</list>
    	</property>
    	<property name="authenticationStrategy">
    		<bean class="org.apache.shiro.authc.pam.AllSuccessfulStrategy"></bean>
    	</property>
    </bean>


项目跑起来可以自己进行测试了


刚刚以上是登录方面的,现在到配置权限

/shiro/src/com/test/shiro/realms/ShiroRealm.java 中的继承类改为 AuthorizingRealm 在实现方法

doGetAuthorizationInfo方法就是实现授权的方法

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection Principals) {
		//1. 从PrincipalCollection 拿到用户的信息
		Object username = Principals.getPrimaryPrincipal();
		
		//2. 拿到登录信息,去获取角色(查询数据库)
		Set<String> roles =new HashSet<>();
		
		
		roles.add("user");
		if("admin".equals(username)){
			roles.add("admin");
		}
		//3.都要实现这个接口返回值
		SimpleAuthorizationInfo info =new SimpleAuthorizationInfo(roles);
		return info;
	}


完成页面


实现注解: 如果出错。权限限制都失效。把这个放到spring-mvc.xml中

	<bean
		class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
		depends-on="lifecycleBeanPostProcessor">
		<property name="proxyTargetClass" value="true" />
	</bean>

	<bean
		class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
		<property name="securityManager" ref="securityManager" />
	</bean>


进行测试。可以发现admin才可以获取到时间


-------

接下来可以将配置权限提取出来

appxxxx.xml

   <bean id="filterChainDefinitionMap"  
     	factory-bean="filterChainDefinitionMapBuilder" factory-method="buildFilterChainDefinitionMap"></bean> 
    
     <bean id="filterChainDefinitionMapBuilder" 
     	class="com.test.shiro.factory.FilterChainDefinitionMapBuilder"></bean> 
    


shiroFilter中加入

 <property name="filterChainDefinitionMap" ref="filterChainDefinitionMap"></property> 
        

创建一个class

/shiro/src/com/test/shiro/factory/FilterChainDefinitionMapBuilder.java

	public LinkedHashMap<String, String> buildFilterChainDefinitionMap() {
		LinkedHashMap<String, String> map =new LinkedHashMap<>();
		map.put("/login.jsp", "anon");
		map.put("/shiro/login", "anon");
		map.put("/shiro/logout", "logout");
		map.put("/user.jsp", "authc,roles[user]");
		map.put("/admin.jsp", "authc,roles[admin]");
		map.put("/list.jsp", "user");
		
		map.put("/**", "authc");
		return map;















































































































































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值