1. 程式人生 > >springMvc的安全登入驗證

springMvc的安全登入驗證

1. 引入springMvc許可權框架security

1-1 配置web.xml

1. 在監聽器上引入許可權局框架的配置檔案security.xml
	 <!--監聽器-->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml,classpath:security.xml</param-value>
    </context-param>
    注意 :<param-value>標籤可以配置多個配置檔案,一般用逗號隔開
 2. 配置過濾器
 <!--filter許可權框架過濾器執行鏈-->
    <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>
注意:filter許可權框架執行鏈要放在解決亂碼的CharacterEncodingFilter過濾器下面,否則會出現中文亂碼

1-2 配置security框架的xml檔案security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:security="http://www.springframework.org/schema/security"
       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.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security.xsd">
    <!--放行頁面不被許可權框架攔截驗證-->
    <security:http pattern="/login.jsp" security="none"></security:http>
    <security:http pattern="/failer.jsp" security="none"></security:http>
    <security:http pattern="/css/**" security="none"></security:http>
    <security:http pattern="/img/**" security="none"></security:http>
    <security:http pattern="/plugins/**" security="none"></security:http>
    <security:http pattern="/pages/**" security="none"></security:http>

    <!--配置攔截的規則
     auto-config="true" 開啟框架的預設配置支援
     use-expressions="false" 關閉表示式的支援
     intercept-url pattern="/**" 攔截所有的請求
     access="ROLE_USER"  擁有ROLE_USER角色的使用者可以訪問資源
     -->
    <security:http auto-config="true" use-expressions="true">
   	 <!--使用springmvc提供的記住登入功能,
	    user-service-ref對映到許可權實現類userService
	    key	瀏覽器訪問存的cookie名稱,隨便起個名字,不用管
		login.jsp裡面記住我複選框checkbox的name屬性必須是“remember-me”,其他無效
		-->
        <security:remember-me user-service-ref="userService" key="rememberUser"></security:remember-me>
        <!--給角色賦予許可權-->
        <security:intercept-url pattern="/**" access="hasAnyRole('ROLE_USER','ROLE_ORDER','ROLE_ADMIN','ROLE_PRODUCT')"></security:intercept-url>
        <!--配置許可權框架自定義面登入節點
         login-page 自定義登入頁
           login-processing-url 登入頁面表單發起登入請求的url路徑
           default-target-url 登入成功跳轉的頁面
           authentication-failure-url 驗證失敗跳轉的頁面
           -->
        <security:form-login login-page="/login.jsp"
                             login-processing-url="/login"
                             default-target-url="/index.jsp"
                             authentication-failure-url="/failer.jsp"></security:form-login>

        <!--登出按鈕的處理節點-->
        <security:logout logout-url="/logout" logout-success-url="/login.jsp" invalidate-session="true"></security:logout>
        <!--訪問資源無許可權拒絕的處理-->
        <security:access-denied-handler error-page="/403.jsp"></security:access-denied-handler>
        <!--csrf攻擊攔截的關閉-->
        <security:csrf disabled="true"></security:csrf>
    </security:http>

    <!--許可權驗證使用自定義的實現類,這裡配置的是userService作為許可權實現類-->
    <security:authentication-manager>
        <security:authentication-provider user-service-ref="userService">
            <!-- 提供加密方式 -->
            <security:password-encoder ref="pwdEncoder"></security:password-encoder>
        </security:authentication-provider>
    </security:authentication-manager>
    <security:global-method-security secured-annotations="enabled"></security:global-method-security>
    <!--通過xml檔案初始化加密的工具類交給容器管理-->
    <bean id="pwdEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean>
</beans>

2. 許可權驗證類UserService的編寫

@Service("userService")
@Transactional
public class userServiceImpl implements UserService ,UserDetailsService {

    @Autowired
    private UserDao userDao;
     @Autowired
    BCryptPasswordEncoder pwdEncoder;
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 通過使用者名稱得到資料庫使用者物件
        SysUser sysUser = userDao.findUserByName(username);
        // 建立使用者的許可權集合
        List<GrantedAuthority> authorities = new ArrayList<>();

        // 查詢到使用者的角色驗證登入
        List<Role> userRoles = sysUser.getRoles();
        // 迴圈新增使用者的角色資訊
        if (userRoles.size()>0 && userRoles != null) {
            for (Role userRole : userRoles) {
                // 初始化賦值給使用者角色
                authorities.add(new SimpleGrantedAuthority(userRole.getRoleName()));
            }
        }
        // 使用資料庫使用者組裝框架需要的user物件用於驗證
        User user = new User(sysUser.getUsername(), sysUser.getPassword(), authorities);
        return user;		// 返回值user帶有使用者名稱username,密碼password和角色即許可權authorties,返回的user是UserDetails 物件,由框架獲取操縱
    }
    /**
    	新增一個使用者,密碼使用BCryptPasswordEncoder 加密,由於在security.xml配置了加密方式,所以登入框架幫你解密,不用管
    	login.jsp登入的form表單提交到在security.xml已經配置好了的"${pageContext.request.contextPath}/login"
    */
      @Override
    public void addUser(SysUser user) {
        //將原始密碼獲取
        String pwd = user.getPassword();
        //將明文加密
        user.setPassword( pwdEncoder.encode(pwd));
        userDao.addUser(user);
    }

3.許可權的控制

3-1.頁面許可權的控制

1.引入標籤庫
	<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
2.表示式驗證
	<security:authorize access="hasRole('ROLE_ADMIN')">
           // 要被許可權框架控制的程式碼
     </security:authorize>
   	例如:
   	 <security:authorize access="hasAnyRole('ROLE_ADMIN')">
   	 <!-- 只有擁有ROLE_ADMIN角色的使用者才能顯示-->
        	<li id="system-setting4">
        	<a href="${pageContext.request.contextPath}/pages/syslog-list.jsp"> <i class="fa fa-circle-o"></i> 訪問日誌
            </a></li>
    </security:authorize>
3.security.xml檔案中開啟表示式支援
// use-expressions="true" 就是開啟表示式支援,完整的上面的security有
	<security:http auto-config="true" use-expressions="true">
		<security:intercept-url pattern="/**" 		 access="hasAnyRole('ROLE_USER','ROLE_ORDER','ROLE_ADMIN','ROLE_PRODUCT')">	</security:intercept-url>

3-2 .後臺程式碼許可權控制

在頁面配置的許可權管理後雖然對沒有許可權的訪問者予以限制,但是仍然可以通過在瀏覽器位址列上訪問路徑,所以使用後臺許可權控制尤為主要
	通過三種註解實現許可權的攔截:
   1.jsr250的方式實現攔截  jsr是java的一個規範 jsr250是對規範的實現 目的是攔截驗證許可權
      引入依賴
      <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>jsr250-api</artifactId>
            <version>1.0</version>
       </dependency>
      在配置檔案中開啟註解支援 為了攔截controller方法配置springMvc中
      約束檔案和名稱空間
      xmlns:security="http://www.springframework.org/schema/security"
      http://www.springframework.org/schema/security          
    		http://www.springframework.org/schema/security/spring-security.xsd
    
    <security:global-method-security jsr250-annotations="enabled"/>
      在需要攔截的類或者方法上通過表示式攔截認證
      @RolesAllowed("ROLE_ADMIN")
   2.secured 註解攔截
       <security:global-method-security secured-annotations="enabled"/>
       @Secured("ROLE_ADMIN")
   3.表示式的註解攔截
   	   <security:global-method-security pre-post-annotations="enabled"/>
   	   @PreAuthorize("hasRole('ROLE_ADMIN')")
	注意:
		1、三種方式都必須在springMvc.xml配置檔案中開啟註解支援
			<!-- 開啟AOP的支援 -->
		<aop:aspectj-autoproxy proxy-target-class="true"/>
		2、推薦使用第二種,次之第三種,不推薦第一種方式,太麻煩了