<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 78, comments - 34, trackbacks - 0, articles - 1
      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

             有沒(méi)有發(fā)現(xiàn)一個(gè)問(wèn)題,我們之前做的所有練習(xí),都沒(méi)的權(quán)限管理這個(gè)模塊。我們的WEB應(yīng)用中的同一個(gè)帳戶可以在多臺(tái)機(jī)器上同時(shí)登陸,每一個(gè)用戶可以操作所有功能模塊。這樣在以后的應(yīng)用開(kāi)發(fā)中是結(jié)對(duì)不可行的!

     

             今天的重點(diǎn)內(nèi)容就是權(quán)限管理,如果使用傳統(tǒng)的方式進(jìn)行權(quán)限管理,在實(shí)現(xiàn)上多少有點(diǎn)麻煩。我在進(jìn)行桌面開(kāi)發(fā)時(shí),涉及到的權(quán)限管理是向用戶表中添加用戶具有的權(quán)限ID串,每次用戶登陸時(shí)都拿這個(gè)串去查詢角色表,并根據(jù)用戶的角色隱藏相應(yīng)的功能。那我們?cè)?/span>WEB應(yīng)用中應(yīng)該如何做呢?方法都一樣,但是Spring為我們提供了一個(gè)框架專門用于權(quán)限管理,用起來(lái)比較方便——security!

            

    一、Spring-security

             SpringSecuritySpringFramework的一個(gè)子項(xiàng)目,之前也叫做AcegiSecruty

             SpringSecurity能用于保護(hù)各種Java應(yīng)用程序(權(quán)限管理框架),但在基于Web的應(yīng)用程序中使用得最為廣泛。

             SpringSecurity能以聲明的方式來(lái)保護(hù)Web應(yīng)用程序的URL訪問(wèn),只需簡(jiǎn)單的配置即可實(shí)現(xiàn)。

             SpringSecurity通過(guò)一系列Servlet過(guò)濾器為Web應(yīng)用程序提供了多種安全服務(wù)。

             SpringSecurity2.x顯著簡(jiǎn)化了配置,使用基于XMLSchema和基于注解的配置。

    clip_image002

             首先讓我們來(lái)回想一下,以前老方在講JavaWEB基礎(chǔ)時(shí)向大家介紹使用Filter進(jìn)行權(quán)限管理,這是一個(gè)十分好的方法。當(dāng)然他也有說(shuō),以后大家學(xué)習(xí)Spring時(shí),只要簡(jiǎn)單的配置幾下就可以進(jìn)行權(quán)限管理了,十分方便。(注意:過(guò)濾器)

     

             Security也正是使用過(guò)濾器來(lái)實(shí)現(xiàn)上面的功能的!能想通嗎?讓我們一點(diǎn)點(diǎn)往下看。        

     

    二、HelloWorld!     

             我們依然從這個(gè)經(jīng)典的程序開(kāi)始,其實(shí)HelloWorld!程序只是學(xué)習(xí)者直觀簡(jiǎn)單的進(jìn)入一門語(yǔ)言或工具。我們的這SecurityHelloWrld程序比較一般的HelloWorld程序內(nèi)容要多一些。我們需要建立兩個(gè)頁(yè)面(index.jspadmin.jsp),index.jsp用于登陸,admin.jsp只有具有ROLE_ADMIN權(quán)限的用戶才能查看。

     

             我們先想一下需求:

    ·         防止一個(gè)帳戶同時(shí)在多個(gè)機(jī)器上登陸

    ·         帳戶只能根據(jù)自己的權(quán)限操作相應(yīng)的功能模塊

    ·         帳戶只能在頁(yè)面上看到具有對(duì)應(yīng)權(quán)限的數(shù)據(jù)內(nèi)容

     

    1.搭建環(huán)境

             因?yàn)槲覀兪褂玫氖?/span>Spring-security,所以需要搭建Spring環(huán)境。創(chuàng)建一個(gè)動(dòng)態(tài)WEB工程(EclipseJavaEE版)。

             1).添加jar包: spring.jar、commons-loggin.jar、spring-security-core-2.0.5.jar。

             2).WEB文件:

    <!-- 搭建Spring -->

    <context-param>

           <param-name>contextConfigLocation</param-name>

           <param-value>/WEB-INF/classes/applicationContext.xml</param-value>

    </context-param>

    <listener>

           <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

    </listener>

     

    <!-- 添加Spring-Security過(guò)濾器 -->

    <filter>

           <filter-name>springSecurityFilterChain</filter-name>

           <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>

    </filter>

    <filter-mapping>

           <filter-name>springSecurityFilterChain</filter-name>

           <url-pattern>/*</url-pattern>

    </filter-mapping> 

             看見(jiàn)沒(méi),在這用到過(guò)濾器代理了!過(guò)濾器名稱必須指定為springSecurityFilterChain,Spring-secrutiy默認(rèn)為我們提供了一個(gè)過(guò)濾器。我們也可以編寫(xiě)一個(gè)自己的過(guò)濾器,然后將它配置為SpringBean,Bean的名稱必須為 springSecurityFilterChain。

     

             3).applicationContext.xml文件:

    <!-- 配置SpringSecurityhttp安全服務(wù) -->

    <sec:http auto-config="true">

           <!-- 只有ROLE_ADMINROLE_USER權(quán)限用戶才能訪問(wèn)index.jsp -->

           <sec:intercept-url pattern="/index.jsp" access="ROLE_ADMIN,ROLE_USER"/>

           <!-- 只有ROLE_ADMIN權(quán)限用戶才能訪問(wèn)admin.jsp -->

             <sec:intercept-url pattern="/admin.jsp" access="ROLE_ADMIN"/>

    </sec:http>

     

    <!-- 配置SpringSecutiry的權(quán)限信息 -->

    <sec:authentication-provider>

           <sec:user-service>

                  <!-- 帳戶信息 -->

                  <sec:user password="admin" name="admin" authorities="ROLE_ADMIN"/>

                  <sec:user password="user" name="user" authorities="ROLE_USER"/>

           </sec:user-service>

    </sec:authentication-provider>

     

             需要為這個(gè)spring的配置文件添加:xmlns:sec="http://www.springframework.org/schema/security",具體操作步驟不細(xì)說(shuō)了。

             Spring的配置文件中描述帳戶、權(quán)限信息,但把這么重要的信息放在這里是不安全的!

     

    2.添加JSP頁(yè)面

             index.jsp,body部分的內(nèi)容:

    <body>

           <h1>*****INDEX*****</h1>

                  <security:authorize ifAllGranted="ROLE_ADMIN">

                         <br>

                         <a href="admin.jsp">ADMIN</a>

                  </security:authorize>

           <br>

           <a href="logout">LOGOUT</a>

    </body>

             需要為這個(gè)JSP文件導(dǎo)入:<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags"%>。

     

             admin.jsp,body部分的內(nèi)容:

    <body>

           <h1>*****ADMIN*****</h1>

           <a href="index.jsp">RETURN</a>

    </body>

     

             OK,我們的Spring-securityHelloWorld!程序已經(jīng)完成了!跑一下,看到這個(gè)頁(yè)面沒(méi)有?

    clip_image004

             我們沒(méi)有為工程添加這們的頁(yè)面??!先不管這些,使用我們配置的兩個(gè)帳戶登陸看看功能如何。

     

    3.登出配置      

             因?yàn)槲覀冊(cè)陧?yè)面中添加了登出連接,所以我們添加一個(gè)登出配置:

    <!-- 配置登出信息 -->

    <logout logout-url="/logout" logout-success-url="/bye.jsp"

           invalidate-session="true" />

             我們添加一個(gè)bye.jsp頁(yè)面,點(diǎn)擊logout連接時(shí),就會(huì)轉(zhuǎn)到此頁(yè)面。

     

    4.登陸配置

             上面的頁(yè)面是spring-security自動(dòng)為我們添加的登陸頁(yè)面,我們也可以設(shè)置自己的登陸頁(yè)面:

    <!-- 配置登陸信息 -->

    <form-login login-page="/login.jsp" login-processing-url="/login" />

     

             login.jsp

    <!-- 配置登陸信息 -->

    <form-login login-page="/login.jsp"

           login-processing-url="/login"                   

             default-target-url="/index.jsp"

           authentication-failure-url="/loginfail.jsp"

           always-use-default-target="true"/>

    login-page:登陸頁(yè)面,這里的login.jsp頁(yè)面中的表單請(qǐng)求和字段名稱必須是spring-security指定的,可以查看spring-security默認(rèn)為我們提供的頁(yè)面代碼。

    login-processing-url:登陸請(qǐng)求處理URL

    default-target-url:登陸成功后,轉(zhuǎn)到的頁(yè)面。

    authentication-failure-url:登陸失敗后,轉(zhuǎn)到的頁(yè)面。

    always-use-default-target:一直使用”default-target-url“,這是什么意思?假如我們現(xiàn)在有兩個(gè)頁(yè)面可以跳到登陸頁(yè)面,默認(rèn)情況下spring-security在登陸成功后會(huì)跳轉(zhuǎn)到——跳轉(zhuǎn)登陸頁(yè)面的頁(yè)面。如果這個(gè)值真,那么登陸成功后會(huì)一直跳轉(zhuǎn)到”default-target-url“指定的頁(yè)面。有些情況下,用戶直接進(jìn)入登陸頁(yè)面進(jìn)行登陸,此時(shí)登陸成功后會(huì)跳轉(zhuǎn)到”default-target-url“指定的頁(yè)面,如果沒(méi)有指定這個(gè)頁(yè)面則跳轉(zhuǎn)到index.jsp頁(yè)面,如果沒(méi)有index.jsp頁(yè)面將出錯(cuò)。

     

    問(wèn)題:

           將這么重要的信息放在spring的配置文件中是相當(dāng)不安全的,Spring-security為們提供了安全的方法,將數(shù)據(jù)放到數(shù)據(jù)庫(kù)中。

     

    三、使用數(shù)據(jù)庫(kù)替換配置文件

             下面我們就實(shí)現(xiàn)將用戶的帳戶信息存儲(chǔ)到數(shù)據(jù)庫(kù)中,關(guān)于頁(yè)面的訪問(wèn)權(quán)限配置存放到數(shù)據(jù)庫(kù)中我們明天再總結(jié)。在此我們就不大動(dòng)干戈去使用Hibernate了,我們使用JDBC。

     

    1.添加JDBC

             Spring添加數(shù)據(jù)源Bean還記得嗎?我們使用的數(shù)據(jù)源是c3p0。

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

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

           <property name="user" value="${user}" />

           <property name="password" value="${password}" />

           <property name="driverClass" value="${driverClass}" />

           <property name="jdbcUrl" value="${jdbcUrl}" />

     

           <property name="minPoolSize" value="5" />

           <property name="initialPoolSize" value="3" />

           <property name="maxPoolSize" value="10" />

           <property name="acquireIncrement" value="2" />

    </bean>

    <bean id="jdbcTemplate"

           class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">

           <constructor-arg ref="dataSource"/>

    </bean>

     

    2.建數(shù)據(jù)庫(kù)和數(shù)據(jù)表

             用戶表與角色表是什么關(guān)系?當(dāng)前是多對(duì)多嘍!因此我們需要三個(gè)表:

             1).user(用戶表)

    clip_image006

             2).role(角色表)

    clip_image008

             3).user_role(中間表)

    clip_image010

    3.從數(shù)據(jù)庫(kù)中讀取權(quán)限信息

             我們的數(shù)據(jù)源、jdbcTemplate和數(shù)據(jù)庫(kù)已經(jīng)建好了,接下來(lái)就是讓spring-security可以讀取到數(shù)據(jù)庫(kù)中的信息,根據(jù)這些信息判斷用戶輸入的登陸信息是否正確以及用戶所具有的權(quán)限。

     

             1).要想spring-security可以讀取到數(shù)據(jù)庫(kù)中的信息,我們必須編寫(xiě)一個(gè)實(shí)現(xiàn)了UserDetailsService接口的類:

    package cn.itcast.cc.spring.security;

     

    import java.util.List;

    import java.util.Map;

    import javax.annotation.Resource;

    import org.springframework.dao.DataAccessException;

    import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;

    import org.springframework.security.GrantedAuthority;

    import org.springframework.security.GrantedAuthorityImpl;

    import org.springframework.security.userdetails.User;

    import org.springframework.security.userdetails.UserDetails;

    import org.springframework.security.userdetails.UserDetailsService;

    import org.springframework.security.userdetails.UsernameNotFoundException;

    import org.springframework.stereotype.Component;

     

    @Component("userDetailsService")

    public class UserDetailsServiceImpl implements UserDetailsService {

     

           @Resource

           private SimpleJdbcTemplate jdbcTemplate = null;

     

           @Override

           public UserDetails loadUserByUsername(String username)

                         throws UsernameNotFoundException, DataAccessException {

                  // 根據(jù)用戶名獲取帳戶和權(quán)限信息

                  String sql = "SELECT username,password,status,name rname"

                                + " FROM user u,role r,user_role ur"

                                + " WHERE u.id=ur.user_id AND r.id=ur.role_id AND username=?";

                  // 如果一個(gè)用戶具有多個(gè)權(quán)限,連接查詢會(huì)返回一個(gè)List

                  List list = this.jdbcTemplate.queryForList(sql,

                                new Object[] { username });

     

                  // 取出帳戶和權(quán)限信息填充到User中返回

                  if (list == null || list.size() <= 0)

                         // spring-security定義的異常

                         throw new UsernameNotFoundException("用戶不存在!");

                  // 如果用戶存在

                  Map<String, Object> map = (Map<String, Object>) list.get(0);

                  // 密碼

                  String password = (String) map.get("password");

                  // 帳戶是否可用

                  boolean enabled = ((Integer) map.get("status") == 1);

                  // 帳戶所具有的權(quán)限

                  GrantedAuthority[] gas = new GrantedAuthority[list.size()];

                  for (int i = 0; i < gas.length; i++) {

                         Map<String, Object> temp = (Map<String, Object>) list.get(i);

                         gas[i] = new GrantedAuthorityImpl((String) temp.get("rname"));

                  }

                  // spring-security提供的類

                  User user = new User(username, password, enabled, true, true, true, gas);

                  return user;

           }

    }

           一定要記住實(shí)現(xiàn)的是UserDetailsService     接口,在spring-security幫助手冊(cè)中應(yīng)該有。佟佟今天領(lǐng)著大家看著源碼,下著斷點(diǎn),找到了這個(gè)接口。

     

             2).applicationContext.xml文件中的<!-- 配置SpringSecutiry的權(quán)限信息 -->部分,全部替換為:

    <authentication-provider user-service-ref="userDetailsService" />

     

             3).運(yùn)行,跑一個(gè)!

     

             Spring-security的實(shí)現(xiàn)原理是什么?查看它的源文件,東西似乎還不少。我們簡(jiǎn)單的想一下,這些功能在Filter中完全可以實(shí)現(xiàn)。我們可以在Filter中讀取數(shù)據(jù)庫(kù)的記錄,根據(jù)帳戶的權(quán)限決定是否允許用戶繼續(xù)訪問(wèn)。我們也可以在JSP頁(yè)面中添加代碼,判斷用戶的權(quán)限以顯示或隱藏相應(yīng)的功能。

             如果我們手動(dòng)去實(shí)現(xiàn)這樣的功能,那還是有些麻煩的。

     

             明天繼續(xù)Spring-sceurity!


    只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
    主站蜘蛛池模板: 麻豆国产精品免费视频| 美女网站在线观看视频免费的| 亚洲成a人片在线看| 亚洲中文字幕久久精品无码2021| 亚洲香蕉在线观看| 99久久婷婷免费国产综合精品| 久久免费精品一区二区| 国产成人免费在线| 国产香蕉九九久久精品免费| 成人国产mv免费视频| 亚洲国产午夜中文字幕精品黄网站| 亚洲一区日韩高清中文字幕亚洲| 亚洲国产精品一区二区久久| 亚洲欧洲在线播放| 美女羞羞免费视频网站| 中文字幕在线免费视频| 精品久久久久久久久免费影院| 国产小视频在线免费| 国产亚洲色视频在线| 亚洲国产日韩在线人成下载| 美女视频黄a视频全免费网站色| 香蕉97超级碰碰碰免费公| 亚洲视频2020| 99热在线日韩精品免费| 亚洲国产综合精品一区在线播放| 亚洲视频无码高清在线| jizz18免费视频| 一个人在线观看视频免费| 亚洲一区二区女搞男| 亚洲一区在线视频观看| 久99久精品免费视频热77| 免费无码又爽又高潮视频| 亚洲人成亚洲人成在线观看| 成年大片免费视频播放一级| 久久国内免费视频| 亚洲综合视频在线观看| xxxxxx日本处大片免费看| 免费视频专区一国产盗摄| 亚洲精品成人久久| 222www免费视频| 亚洲无码精品浪潮|