Spring Security框架的一些琐碎基本配置备忘

2014-10-20 • 技术文章评论

XML配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:security="http://www.springframework.org/schema/security" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/security   
        http://www.springframework.org/schema/security/spring-security-3.2.xsd">
    <!-- **跨目录,*不跨目录匹配 -->
    <security:http auto-config="false" pattern="/admin/**" use-expressions="true" 
        access-denied-page="/error.html" authentication-manager-ref="adminAuthManager" 
        entry-point-ref="loginUrlAuthenticationEntryPoint">
        <!-- access: permitAll denyAll isFullyAuthenticated() hasAnyRole() hasRole()... -->
        <security:intercept-url pattern="/admin/*" access="permitAll"/>
        <!-- 自定义过滤器,可以在其中实现验证码等必要的配置 -->
        <security:custom-filter ref="adminCaptchaFilter" position="FORM_LOGIN_FILTER"/>
        <!-- 注销登出配置 -->
        <security:logout invalidate-session="true" logout-success-url="/admin/?msg=out" logout-url="/admin/signout" />
        <security:session-management>
            <security:concurrency-control error-if-maximum-exceeded="false" max-sessions="1" />
        </security:session-management>
    </security:http>
    <!-- 登录配置 -->
    <bean id="loginUrlAuthenticationEntryPoint" 
        class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
        <property name="loginFormUrl" value="/admin/?msg=auth"/>
    </bean>
    <bean id="adminCaptchaFilter" class="org.tehon.eg.adminCaptchaFilter">
        <property name="filterProcessesUrl" value="/amdin/signin"/>
        <property name="authenticationManager" ref="adminAuthManager"/>
        <property name="authenticationSuccessHandler" ref="adminAuthSuccessHandler"/>
        <property name="authenticationFailureHandler" ref="adminAuthFailureHandler"/>
        <property name="allowSessionCreation" value="true"/>
    </bean>
    <security:authentication-manager id="adminAuthManager">
        <!-- 自定义用户信息、密码加密策略 -->
        <security:authentication-provider user-service-ref="adminDetailService">
            <security:password-encoder ref="PD" />
        </security:authentication-provider>
    </security:authentication-manager>
    <!-- 密码加密,实现encode(CharSequence)和matches(CharSequence,String) -->
    <bean id="PD" class="org.tehon.eg.PasswordDigest" />
    <bean id="adminDetailService" class="org.tehon.eg.adminAuthService" />
    <!-- 自定义实现登录成功的一些处理 -->
    <bean id="adminAuthSuccessHandler" class="org.tehon.eg.adminAuthSuccessHandler">
        <property name="defaultTargetUrl" value="/admin/index.jsp"/>
    </bean>
    <!-- 自定义实现登录失败的一些处理 -->
    <bean id="adminAuthFailureHandler" class="org.tehon.eg.adminAuthFailureHandler">
        <property name="defaultFailureUrl" value="/admin/?msg=fail"/>
    </bean>
    <!-- 自定义错误提示信息 -->
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <!-- 文件名,不加扩展名 -->
                <value>spring-sec-msg_zh_CN</value>
            </list>
        </property>
    </bean>
</beans>

自定义User

写一个类继承org.springframework.security.core.userdetails.User,在其中加一些需要的成员及其getter/setter,实现新的构造函数。

1
2
3
4
5
private String name;
public adminUser(String email, String pwd, boolean a1, boolean a2, boolean a3, boolean a4, Collection<GrantedAuthority> a, String name) {
    super(email, pwd, a1, a2, a3, a4, a);
    this.name = name;
}

自定义UserDetailsService

写一个类实现UserDetailsService,Override其loadUserByUsername(String)方法。

1
2
3
4
5
6
7
8
9
10
11
@Override
public UserDetails loadUserByUsername(String email) throws BadCredentialsException {
    Admin admin = adminDao.queryByEmail(email);
    AdminUser userDetail = null;
    if(admin != null){
        userDetail = new AdminUser(...);
    } else {
        throw new BadCredentialsException("登录邮箱地址无效,请确认!");
    }
    return userDetail;
}

角色权限

Spring Security中有很多各种各种的对象,但阅读其源代码可以发现大多是一堆堆的String。比如对角色而言,我们可以把String类型传入直接构造。这里的角色和HttpServletRequest中的Role是相通的。

1
2
Collection<GrantedAuthority> gas = new ArrayList<GrantedAuthority>();
gas.add(new SimpleGrantedAuthority("ROLE_SUPERUSER"));

自定义实现验证码

写一个类继承org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter,Override其attemptAuthentication方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
        HttpServletResponse response) throws AuthenticationException {
 
    String requestCaptcha = request.getParameter("j_captcha").toLowerCase();
    String genCaptcha = (String)request.getSession().getAttribute("captcha");
 
    // 验证码验证完一次后销毁
    request.getSession().setAttribute("captcha", null);
 
    if(StringUtils.isBlank(requestCaptcha) || StringUtils.isBlank(genCaptcha) || !genCaptcha.equals(requestCaptcha)){
        throw new AuthenticationServiceException("验证码错误!");
    }
 
    return super.attemptAuthentication(request, response);
}