spring項目框架的搭建(2):整合權限框架shiro

結合《spring項目框架的搭建(1):基本搭建》代碼,在此基礎上完成shiro的整合。java

整合前的準備web

  1. 須要引入shiro相關的jar
  2. 須要一個realm給登陸用戶進行認證受權
  3. 添加shiro的配置文件,指定url的過濾規則
  4. web.xml配置shiro過濾
  5. 登陸控制器調用
  • pom.xml內容追加一下幾個依賴
<!--shiro-->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>${shiro.version}</version>
        </dependency>

<shiro.version>1.4.0</shiro.version> 表示shiro使用的版本號,這裏使用的當前時間的最新版本。spring

  • 建立認證受權的Realm,這個類主要的做用是進行登陸用戶的身份認證和權限認證。

新建一個ShiroDbRealm.java類繼承AuthorizingRealm,複寫父類中的兩個方法apache

doGetAuthorizationInfo,AuthenticationInfo;使用 @Component註解將對象交給容器管理。api

僞代碼以下:緩存

/**
     * 受權查詢回調函數, 進行鑑權但緩存中無用戶的受權信息時調用.
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //獲取當前登陸的用戶名,等價於(String)principals.fromRealm(this.getName()).iterator().next()
        String currentUsername = (String)super.getAvailablePrincipal(principals);
        Admin admin=adminService.findByUserName(currentUsername);
        List<String> roles = new ArrayList<String>();//存放該用戶具有的角色
        List<String> permissions = new ArrayList<String>();//存放該用戶具有的權限

        //查詢用戶擁有的角色和對應的權限
        List<AdminRole> adminRolesList=adminRolesService.findByAdminId(admin.getId());
        if(adminRolesList!=null && adminRolesList.size()>0){
            Role role;
            for (AdminRole adminRoles:adminRolesList){
                role=roleService.get(Role.class,adminRoles.getRoleId());
                roles.add(role.getRoleName());
                RolePermission permission=roleService.findRolePermission(role.getId());
                if (permission!=null){
                    permissions.addAll(permission.getPermissionList());
                }
            }

        }



        //用來保存認證好的信息,
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        if (admin.getIdentity()==1){
            info.addRole("admin");
            info.addStringPermission("*:*");
        }else {
            info.addRoles(roles);
            info.addStringPermissions(permissions);
        }

        return info;
    }

    /**
     * 認證回調函數,登陸時調用.
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;
        Admin admin=adminService.findByUserName(token.getUsername());
        if (admin!=null){
            return new SimpleAuthenticationInfo(admin.getUsername(),admin.getPassword(),admin.getRealName());
        }else {
            return null;
        }

    }

AuthenticationInfo登陸成後會執行此方法,可是須要在登陸成功後的位置顯示調用subject.login(token).安全

身份認證成功後會進入doGetAuthorizationInfo進行權限認證和存儲。session

  • 配置spring-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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
    <description>Shiro安全配置</description>
    <!-- Shiro 安全管理器-->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="shiroDbRealm"/>
    </bean>

    <!-- Shiro 過濾器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!--shiro 核心權限管理器 必須配置-->
        <property name="securityManager" ref="securityManager"/>
        <!--身份認證失敗跳轉的登陸頁面-->
        <property name="loginUrl" value="/admin/login"/>
        <!--認證成功跳轉的指定頁面-->
        <property name="successUrl" value="/admin/index"/>
        <!--權限認證失敗跳轉的指定頁面-->
        <property name="unauthorizedUrl" value="/admin/unautho"/>
        <!--url 過濾規則-->
        <property name="filterChainDefinitions">
            <value>
                /admin/login = anon
                /admin/doLogin = anon
                /admin/logout = authc
                /admin/unautho=anon
                <!--/admin/** = [*:*]-->
            </value>
        </property>
    </bean>

    <!-- 保證明現了Shiro內部lifecycle函數的bean執行 -->
    <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
     
    <!-- 開啓Shiro註解  AOP式方法級權限檢查  -->
    <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>

</beans>

同時在spring.xml中添加    <import resource="spring-shiro.xml"/>app

  • 配置web.xml
<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
      <!-- 該值缺省爲false,表示生命週期由SpringApplicationContext管理,設置爲true則表示由ServletContainer管理 -->
      <param-name>targetFilterLifecycle</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>/admin/*</url-pattern>
  </filter-mapping>
  • LoginController.java
@RequestMapping(value = "doLogin",method = RequestMethod.POST)

    public ApiBean doLogin(String username, String password, Boolean rememberMe, HttpSession session, HttpServletRequest request){
        ApiBean apiBean;

        if (StrKit.notNull(username,password)) {
             //驗證用戶名密碼是否正確
            JSONObject loginRes=adminService.login(username,password);

            if (loginRes.getBoolean("login")){
                Admin admin= (Admin) loginRes.get("admin");
                UsernamePasswordToken token = new UsernamePasswordToken(admin.getUsername(),admin.getPassword());
                Subject subject = SecurityUtils.getSubject();
                subject.login(token);
                apiBean= ApiBean.responseSuccess("登陸成功");
            } else {
                apiBean= ApiBean.responseError(loginRes.getString("msg"));
            }



        } else {
            apiBean= ApiBean.responseError("用戶名密碼錯誤");
        }
        return apiBean;

    }

當subject.login(token)以後,會進入到自定義的realm中的AuthenticationInfo方法,該方法執行完成後會執行doGetAuthorizationInfo方法。在這裏我顯示的調用了service裏的方法去驗證用戶名密碼是否正確,在正確以後再將用戶交由shiro進行二次身份覈實和權限認證。框架

相關文章
相關標籤/搜索