shiro再次学习

xiaoxiao2021-02-28  80

编辑器要配置好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;

转载请注明原文地址: https://www.6miu.com/read-75060.html

最新回复(0)