天天看點

spring security 3.0 的 使用者詳細資訊的 session 擴充 (基于rapid framework)

applicationContext-security.xml:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:s="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-2.5.xsd

                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd"

    default-autowire="byType" default-lazy-init="true">

    <description>使用SpringSecurity的安全配置檔案</description>

    <!-- http安全配置 -->

    <s:http auto-config="true" access-decision-manager-ref="accessDecisionManager">

        <s:form-login login-page="/pages/Login/login.do" />

        <s:logout logout-success-url="/" />

        <s:remember-me key="ssss" />

    </s:http>

    <!-- 自定義成功和失敗處理器,AppSessionSuccessHandler中設定了session -->

    <bean id="appSessionProcessingFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationProcessingFilter"> 

        <s:custom-filter before="AUTHENTICATION_PROCESSING_FILTER" />

        <property name="authenticationFailureHandler"> 

            <bean class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"> 

                <property name="defaultFailureUrl" value="/pages/Login/login.do?error=true"/> 

            </bean> 

        </property> 

        <property name="authenticationSuccessHandler"> 

            <bean class="javacommon.base.AppSessionSuccessHandler"> 

                <property name="defaultTargetUrl" value="/"/> 

        </property>

    </bean>   

    <!-- 認證配置 -->

    <s:authentication-provider user-service-ref="userDetailsService">

        <!-- 可設定hash使用sha1或md5散列密碼後再存入資料庫 -->

        <s:password-encoder hash="plaintext" />

    </s:authentication-provider>

    <!-- 項目實作的使用者查詢服務 -->

    <bean id="userDetailsService" class="com.awd.service.UserDetailServiceImpl" />

    <!-- 重新定義的FilterSecurityInterceptor,使用databaseDefinitionSource提供的url-授權關系定義 -->

    <bean id="filterSecurityInterceptor" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">

        <s:custom-filter before="FILTER_SECURITY_INTERCEPTOR" />

        <property name="accessDecisionManager" ref="accessDecisionManager" />

        <property name="objectDefinitionSource" ref="databaseDefinitionSource" />

    </bean>

    <!-- DefinitionSource工廠,使用resourceDetailService提供的URL-授權關系. -->

    <bean id="databaseDefinitionSource" class="javacommon.base.DefinitionSourceFactoryBean">

        <property name="resourceDetailService" ref="resourceDetailService" />

    <!-- 項目實作的URL-授權查詢服務 -->

    <bean id="resourceDetailService" class="com.awd.service.ResourceDetailServiceImpl" />

    <!-- 授權判斷配置, 将授權名稱的預設字首由ROLE_改為A_. -->

    <bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">

        <property name="decisionVoters">

            <list>

                <bean class="org.springframework.security.access.vote.RoleVoter">

                    <property name="rolePrefix" value="A_" />

                </bean>

                <bean class="org.springframework.security.access.vote.AuthenticatedVoter" />

            </list>

</beans>

AppSessionSuccessHandler:

package javacommon.base;

import java.io.IOException;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.security.core.Authentication;

import org.springframework.security.core.userdetails.UserDetails;

import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;

import org.springframework.security.web.savedrequest.SavedRequest;

import org.springframework.security.web.util.RedirectUtils;

import org.springframework.transaction.annotation.Transactional;

import org.springframework.util.StringUtils;

import com.awd.dao.UsersDao;

import com.awd.model.Users;

@Transactional(readOnly = true)

public class AppSessionSuccessHandler extends

        SavedRequestAwareAuthenticationSuccessHandler {

    @Autowired

    private UsersDao usersDao;

    public void onAuthenticationSuccess(HttpServletRequest request,

            HttpServletResponse response, Authentication authentication)

            throws ServletException, IOException {

        SavedRequest savedRequest = getSavedRequest(request);

        if (savedRequest == null) {

            super.onAuthenticationSuccess(request, response, authentication);

            return;

        }

        if (isAlwaysUseDefaultTargetUrl()

                || StringUtils.hasText(request

                        .getParameter(getTargetUrlParameter()))) {

            removeSavedRequest(request);

        // 參考Lingo 的Spring security 3.0文檔 附錄 C. Spring Security-3.0.0.M1

        HttpSession session = request.getSession();

        UserDetails userDetails = (UserDetails) authentication.getPrincipal();

        Users currentUser = usersDao.findByUnique("loginname", userDetails.getUsername().toString());

        session.setAttribute("currentUser", currentUser);

        // Use the SavedRequest URL

        String targetUrl = savedRequest.getFullRequestUrl();

        logger.debug("Redirecting to SavedRequest Url: " + targetUrl);

        RedirectUtils.sendRedirect(request, response, targetUrl,

                isUseRelativeContext());

    }

    private SavedRequest getSavedRequest(HttpServletRequest request) {

        HttpSession session = request.getSession(false);

        if (session != null) {

            return (SavedRequest) session

                    .getAttribute(SavedRequest.SPRING_SECURITY_SAVED_REQUEST_KEY);

        return null;

    private void removeSavedRequest(HttpServletRequest request) {

            logger.debug("Removing SavedRequest from session if present");

            session

                    .removeAttribute(SavedRequest.SPRING_SECURITY_SAVED_REQUEST_KEY);

}

UserDetailServiceImpl.java

package com.awd.service;

import java.util.HashSet;

import java.util.Set;

import org.springframework.dao.DataAccessException;

import org.springframework.security.core.GrantedAuthority;

import org.springframework.security.core.authority.GrantedAuthorityImpl;

import org.springframework.security.core.userdetails.UserDetailsService;

import org.springframework.security.core.userdetails.UsernameNotFoundException;

import com.awd.model.Authorities;

import com.awd.model.Roles;

/**

 * 實作SpringSecurity的UserDetailsService接口,實作擷取使用者Detail資訊的回調函�數.

 * 

 * @author calvin  edit by meetrice

 */

public class UserDetailServiceImpl implements UserDetailsService {

    /**

     * 擷取使用者Detail資訊的回調函�數.

     */

    public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException {

        Users users = usersDao.findByUnique("loginname", userName);

        if (users == null)

            throw new UsernameNotFoundException("使用者" + userName + " 不存在");

        GrantedAuthority[] grantedAuths = obtainGrantedAuthorities(users);

        // 無以下屬性,暫時全部設為true.

        boolean enabled = true;

        boolean accountNonExpired = true;

        boolean credentialsNonExpired = true;

        boolean accountNonLocked = true;

        org.springframework.security.core.userdetails.User userdetail = new org.springframework.security.core.userdetails.User(

                users.getLoginname(), users.getPassword(), enabled, accountNonExpired, credentialsNonExpired,

                accountNonLocked, grantedAuths);

        return userdetail;

     * 獲得使用者所有角色的權限.

    private GrantedAuthority[] obtainGrantedAuthorities(Users user) {

        Set<GrantedAuthority> authSet = new HashSet<GrantedAuthority>();

        for (Roles role : user.getRoles()) {

            for (Authorities authority : role.getAuthorities()) {

                authSet.add(new GrantedAuthorityImpl(authority.getName()));

            }

        return authSet.toArray(new GrantedAuthority[authSet.size()]);