Shiro

【shiro】


Authentication :身份认证/登录,验证用户是不是拥有相应的身份;
Authorization : 授权,即权限验证,验证即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;
Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
Web Support:Web支持,可以非常容易的集成到Web环境;
Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;
Concurrency:shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
Testing:提供测试支持;
Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。


记住一点,Shiro不会去维护用户、维护权限;这些需要我们自己去设计/提供;然后通过相应的接口注入给Shiro即可。




Applicationcontext-shiro.xml代码  收藏代码
<?xml version="1.0" encoding="UTF-8"?>  
<beans xmlns="http://www.springframework.org/schema/beans"  
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
       xmlns:util="http://www.springframework.org/schema/util"  
       xsi:schemaLocation="  
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">  
  
    <description>Shiro 配置</description>  
    <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="/index.jsp" />  
        <property name="unauthorizedUrl" value="/login.do" />  
        <property name="filterChainDefinitions">  
            <value>  
                /login.jsp = anon  
                /login.do = anon  
                /** = authc  
               </value>  
        </property>  
    </bean>  
  
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
        <!--设置自定义realm-->  
        <property name="realm" ref="monitorRealm" />  
    </bean>  
  
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />  
      
    <!--自定义Realm 继承自AuthorizingRealm-->  
    <bean id="monitorRealm" class="***module.system.security.MonitorRealm"></bean>  
    <!-- securityManager -->  
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">  
        <property name="staticMethod"  
            value="org.apache.shiro.SecurityUtils.setSecurityManager" />  
        <property name="arguments" ref="securityManager" />  
    </bean>  
      
    <!-- Enable Shiro Annotations for Spring-configured beans.  Only run after -->  
    <!-- the lifecycleBeanProcessor has run: -->  
    <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>  
</beans>  
 
 
将shiro的配置文件引入到web.xml中:
 
 
 
并在web.xml中加入如下代码:
 
 
 
 
Xml代码  收藏代码
<!-- Shiro Security filter -->  
    <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>*.do</url-pattern>  
    </filter-mapping>  
    <filter-mapping>  
        <filter-name>shiroFilter</filter-name>  
        <url-pattern>*.jsp</url-pattern>  
    </filter-mapping>  
 
实现自己的Realm
 
Java代码  收藏代码
@Service("monitorRealm")  
public class MonitorRealm extends AuthorizingRealm {  
      
    @Autowired UserService userService;  
    @Autowired RoleService roleService;  
    @Autowired LoginLogService loginLogService;  
      
    public MonitorRealm(){  
        super();  
  
    }  
      
    @Override  
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {  
        /*这里编写授权代码*/  
          
    }  
  
    @Override  
    protected AuthenticationInfo doGetAuthenticationInfo(  
            AuthenticationToken authcToken) throws AuthenticationException {  
    /*这里编写认证代码*/  
    }  
      
    public void clearCachedAuthorizationInfo(String principal) {  
        SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());  
        clearCachedAuthorizationInfo(principals);  
    }  
  
}  
 
登录时的代码示例:
 
Java代码  收藏代码
Subject currentUser = SecurityUtils.getSubject();  
        if(!currentUser.isAuthenticated()){  
            UsernamePasswordToken token;  
            if(null == rememberMe)  
                token = new UsernamePasswordToken(user.getUsername(), EncryptUtils.encodeMD5String(user.getPassword()),false,request.getRemoteAddr());  
            else token = new UsernamePasswordToken(user.getUsername(), EncryptUtils.encodeMD5String(user.getPassword()), true, request.getRemoteAddr());  
            try {  
                currentUser.login(token);  
            } catch ( AuthenticationException ae ) {  
                request.setAttribute("message", "用户名或密码错误!");  
                return "login";  
            }  
        }  
 执行currentUser.login(token);这句代码时,shiro会自动调用用户实现的Realm的doGetAuthenticationInfo进行身份认证。
登出时的代码示例:
 
Java代码  收藏代码
Subject currentUser = SecurityUtils.getSubject();  
        if (currentUser != null) {  
            currentUser.logout();  
        }  
        HttpSession session = request.getSession(false);  
        if( session != null ) {  
            session.invalidate();  
        }  
        return "login";  

 在对用户(角色)进行授权时会执行Realm里的doGetAuthorizationInfo方法。

————————————————————————————————————————————

web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <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>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>ERROR</dispatcher>
  </filter-mapping>
</web-app>
-------------------------------------------------------------------------
servlet-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task" 
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/task  
        http://www.springframework.org/schema/task/spring-task-3.1.xsd">


<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />


<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />


<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/view directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>

<context:component-scan base-package="com.bicycle.web" />

<tx:annotation-driven/>


<!-- a PlatformTransactionManager is still required -->
<beans:bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<beans:property name="dataSource">
<beans:ref bean="dataSource"/>
</beans:property>
</beans:bean>

<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<beans:property name="defaultEncoding" value="UTF-8"/> <!-- 默认编码 -->      
   <beans:property name="maxInMemorySize" value="4096"/> <!-- 最大内存大小 -->  
   <beans:property name="maxUploadSize" value="-1"/> <!-- 最大文件大小,-1为无限制 -->
</beans:bean>

<!-- SpringMVC在超出上传文件限制时,会抛出org.springframework.web.multipart.MaxUploadSizeExceededException -->
<!-- 该异常是SpringMVC在检查上传的文件信息时抛出来的,而且此时还没有进入到Controller方法中 -->
<beans:bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<beans:property name="exceptionMappings">
<beans:props>
<!-- 遇到MaxUploadSizeExceededException异常时,自动跳转到/WEB-INF/views/fileError.jsp页面 -->
<beans:prop key="org.springframework.web.multipart.MaxUploadSizeExceededException">fileError</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
    
    <!-- Enable Shiro Annotations for Spring-configured beans.  Only run after -->
<!-- the lifecycleBeanProcessor has run: -->
<beans:bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
<beans:property name="proxyTargetClass" value="true" />
</beans:bean>
<beans:bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    <beans:property name="securityManager">
    <beans:ref bean="securityManager"/>
    </beans:property>
</beans:bean>

<!-- Enables the Spring Task @Scheduled programming model -->   
<task:executor id="executor" pool-size="5" /> 
<task:scheduler id="scheduler" pool-size="10" /> 
<task:annotation-driven executor="executor" scheduler="scheduler" />
<!-- 加载cron 系统配置  -->
<context:property-placeholder location="classpath:project.properties"/> 

</beans:beans>


---------------------------------------------------------------------
root-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

<!-- Root Context: defines shared resources visible to all other web components -->

<context:property-placeholder location="classpath:project.properties"/>
<context:property-placeholder location="classpath:sql.properties"/> 

<import resource="classpath*:datasource.xml"/>

<!-- Security Configuration / Apache Shiro -->
<import resource="shiro-context.xml"/>
</beans>


-----------------------------------------------------------------------
<注:springboot配置之一>
shiro-context.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">


<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login"/> 
<property name="successUrl" value="/main"/>
<property name="unauthorizedUrl" value="/unauthorized"/>

<property name="filterChainDefinitions">
<value>
/login = anon
/resources/** = anon
/** = authc
</value>
</property> 
</bean>

<bean id="sampleRealm" class="org.apache.shiro.realm.jdbc.JdbcRealm">
<property name="dataSource" ref="dataSource"/>
  </bean>

<bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
  </bean>
 
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="sampleRealm" /> 
<property name="cacheManager" ref="shiroCacheManager"/>
</bean>

<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />

<import resource="classpath*:shiro-realm.xml"/>

</beans>
----------------------------------------------------------------
<注:springboot配置之二>
shiro-realm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
             
<!-- Define the Shiro Realm implementation you want to use to connect to your back-end -->
<!-- security datasource: -->
<bean id="jdbcRealm" class="org.apache.shiro.realm.jdbc.JdbcRealm">
<property name="dataSource" ref="dataSource"/>
<property name="authenticationQuery" value="SELECT passphrase, CONCAT('${shiro.applicationSalt}', ':', salt) as salt FROM users where userid = ?"/>
<property name="userRolesQuery" value="SELECT name FROM roles LEFT JOIN user_roles ON roles.id = user_roles.role_id LEFT JOIN users ON user_roles.user_id = users.id WHERE userid = ?"/>
<property name="permissionsQuery" value="SELECT permission FROM role_permissions LEFT JOIN roles ON role_permissions.role_id = roles.id WHERE roles.name = ?"/>
<property name="permissionsLookupEnabled" value="true"/>
<property name="saltStyle" value="COLUMN"/>
<property name="credentialsMatcher" ref="sha512Matcher"/>
</bean>
</beans>
----------------------------------------------------------------
Controller部分:
@RequestMapping(value="/login",method=RequestMethod.POST)
public String login(@Validated UserFormBean loginUser, BindingResult result, HttpServletRequest request, Model model){
String loginMessage = null;
if(result.hasErrors()){
loginMessage = "Username or password cannot be empty, please enter again!";
model.addAttribute("loginMessage", loginMessage);
return "Bicycle/login";
}


String username = loginUser.getName();
String userpwd = loginUser.getPassword();
UsernamePasswordToken token = new UsernamePasswordToken(username, userpwd);
Subject currentUser = SecurityUtils.getSubject();
try{
currentUser.login(token);
SecurityUtils.getSubject().getSession().setTimeout(21600000);
}catch(UnknownAccountException e){ //不认识的账户
    loginMessage = "Username or password error, please check!";
    model.addAttribute("loginMessage", loginMessage);
       return "Bicycle/login";
   }catch(IncorrectCredentialsException e){ //密码错误
    loginMessage = "Username or password error, please check!";
    model.addAttribute("loginMessage", loginMessage);
       return "Bicycle/login";
   }catch(AuthenticationException e){ //登录出错的总异常类
    loginMessage = "Validation exceptions: ";
    model.addAttribute("loginMessage", loginMessage + e.getMessage());
       return "Bicycle/login";
   }

return "redirect:/main";
}


----------------------------------------
AuthenticationException 异常类的子类有:


UsernameNotFoundException 用户找不到


BadCredentialsException 坏的凭据


AccountStatusException 用户状态异常它包含如下子类


AccountExpiredException 账户过期


LockedException
账户锁定


DisabledException
 账户不可用


CredentialsExpiredException
 证书过期


-----------------------------------------
pom.xml添加的依赖:
<properties>
<org.apache.shiro-version>1.2.6</org.apache.shiro-version>
</properties>


<dependencies>
<!-- security -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${org.apache.shiro-version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${org.apache.shiro-version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${org.apache.shiro-version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${org.apache.shiro-version}</version>
</dependency>
</dependencies>



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值