zoukankan      html  css  js  c++  java
  • SpringSecurity自定义过滤器

    applicationContext-security.xml:


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

    <!-- 访问被拒绝时跳转到403界面 -->
    <http entry-point-ref="authenticationProcessingFilterEntryPoint"
    access-denied-page="/403.jsp" >
    <!-- 放行页面 -->
    <intercept-url pattern="/*.css" filters="none" />
    <intercept-url pattern="/error.jsp" filters="none" />
    <intercept-url pattern="/index*.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="any" />
    <!-- 访问全部要通过身份验证 -->
    <intercept-url pattern="/**" access="isAuthenticated()" />
    <!-- 访问全部要有ROLE_USER权限 -->
    <intercept-url pattern="/**" access="ROLE_USER" />

    <!-- 安全退出后的页面 -->
    <logout logout-success-url="/logout.jsp" />
    <!-- 两周内记住我 -->
    <remember-me key="jbcpPetStore" />

    <!-- 检测失效的sessionId,超时时定位到另外一个URL, -->
    <session-management
    session-authentication-error-url="/No_certification.jsp"
    invalid-session-url="/index.jsp" session-fixation-protection="migrateSession">
    <!-- 防止多端登录 -->
    <concurrency-control max-sessions="1"
    error-if-maximum-exceeded="true" expired-url="/error.jsp" />
    </session-management>

    <custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER" />
    </http>

    <!-- 自定义登录过滤 -->
    <beans:bean id="loginFilter"
    class="filter.UsernamePasswordAuthenticationExtendFilter">
    <!-- 验证页面 -->
    <beans:property name="filterProcessesUrl" value="/j_spring_security_check" />
    <!-- 验证成功后的处理 -->
    <beans:property name="authenticationSuccessHandler"
    ref="loginLogAuthenticationSuccessHandler" />
    <!-- 验证失败后的处理 -->
    <beans:property name="authenticationFailureHandler"
    ref="simpleUrlAuthenticationFailureHandler" />
    <!-- 认证器 -->
    <beans:property name="authenticationManager" ref="authenticationManager" />

    </beans:bean>

    <!-- 认证器 -->
    <authentication-manager alias="authenticationManager">
    <authentication-provider user-service-ref='myUserDetailsService' />
    </authentication-manager>

    <!-- 注入认证器 -->
    <beans:bean id="myUserDetailsService" class="filter.MyUserDetailService" />

    <!-- 开始注入登录过滤器 -->
    <beans:bean id="loginLogAuthenticationSuccessHandler"
    class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
    <beans:property name="defaultTargetUrl" value="/welcome.jsp"></beans:property>
    </beans:bean>
    <beans:bean id="simpleUrlAuthenticationFailureHandler"
    class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
    <beans:property name="defaultFailureUrl" value="/index.jsp?error=true"></beans:property>
    </beans:bean>
    <!-- 注入登录过滤器结束 -->

    <beans:bean id="authenticationProcessingFilterEntryPoint"
    class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <beans:property name="loginFormUrl" value="/index.jsp"></beans:property>
    </beans:bean>

    </beans:beans>

    web.xml:


    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">
    <display-name></display-name>
    <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <!-- 防止请求Spring乱码 -->
    <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
    <param-name>encoding</param-name>
    <param-value>utf-8</param-value>
    </init-param>
    <init-param>
    <!--强制转换编码(request和response均适用) -->
    <param-name>ForceEncoding</param-name>
    <param-value>true</param-value>
    </init-param>
    </filter>
    <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- Spring Security过滤器 -->
    <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>
    <!-- Struts2 -->
    <filter>
    <filter-name>struts2</filter-name>
    <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>struts2</filter-name>
    <url-pattern>*.action</url-pattern>
    </filter-mapping>
    <!-- Spring -->
    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml,classpath:applicationContext-security.xml</param-value>
    </context-param>
    <!-- Spring监听 -->
    <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <!-- 监听session 防止多端登录 -->
    <listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
    </listener>
    <!-- session有效期为30分 -->
    <session-config>
    <session-timeout>30</session-timeout>
    </session-config>
    </web-app>

    继承UsernamePasswordAuthenticationFilter类的代码:


    package filter;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.springframework.security.authentication.AuthenticationServiceException;
    import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
    import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;

    /**
    * 重载SECURITY3的UsernamePasswordAuthenticationFilter的attemptAuthentication,
    * obtainUsername,obtainPassword方法(完善逻辑) 增加验证码校验模块 添加验证码属性 添加验证码功能开关属性
    *
    * @author shadow
    * @email 124010356@qq.com
    * @create 2012.04.28
    */
    public class UsernamePasswordAuthenticationExtendFilter extends UsernamePasswordAuthenticationFilter {

    private SessionAuthenticationStrategy sessionAuthenticationStrategy = null;


    public SessionAuthenticationStrategy getSessionAuthenticationStrategy() {
    return sessionAuthenticationStrategy;
    }

    public void setSessionAuthenticationStrategy(
    SessionAuthenticationStrategy sessionAuthenticationStrategy) {
    this.sessionAuthenticationStrategy = sessionAuthenticationStrategy;
    }

    // 验证码字段
    private String validateCodeParameter = "validateCode";
    // 是否开启验证码功能
    private boolean openValidateCode = false;

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
    HttpServletResponse response) throws AuthenticationException {
    request.getSession().removeAttribute("msg");
    // 只接受POST方式传递的数据
    if (!"POST".equals(request.getMethod())){
    throw new AuthenticationServiceException("不支持非POST方式的请求!");
    }

    // 开启验证码功能的情况
    if (isOpenValidateCode()){
    checkValidateCode(request);
    }

    // 获取Username和Password
    String username = obtainUsername(request);
    String password = obtainPassword(request);

    // UsernamePasswordAuthenticationToken实现Authentication校验
    UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
    username, password);

    // 允许子类设置详细属性
    setDetails(request, authRequest);

    // 运行UserDetailsService的loadUserByUsername 再次封装Authentication
    return this.getAuthenticationManager().authenticate(authRequest);
    }

    // 匹对验证码的正确性
    public void checkValidateCode(HttpServletRequest request) {
    String jcaptchaCode = obtainValidateCodeParameter(request);
    if (null == jcaptchaCode || "".equals(jcaptchaCode)){
    throw new AuthenticationServiceException("请输入验证码");
    }
    if(null == request.getSession().getAttribute("rand")){
    throw new AuthenticationServiceException("验证码失效");
    }
    //对比普通验证码
    if(!request.getSession().getAttribute("rand").equals(jcaptchaCode)){
    throw new AuthenticationServiceException("验证码错误!");
    }
    return;
    }

    public String obtainValidateCodeParameter(HttpServletRequest request) {
    Object obj = request.getParameter(getValidateCodeParameter());
    return null == obj ? "" : obj.toString().trim();
    }

    @Override
    protected String obtainUsername(HttpServletRequest request) {
    Object obj = request.getParameter(getUsernameParameter());
    return null == obj ? "" : obj.toString().trim();
    }

    @Override
    protected String obtainPassword(HttpServletRequest request) {
    Object obj = request.getParameter(getPasswordParameter());
    return null == obj ? "" : obj.toString().trim();
    }

    public String getValidateCodeParameter() {
    return validateCodeParameter;
    }

    public void setValidateCodeParameter(String validateCodeParameter) {
    this.validateCodeParameter = validateCodeParameter;
    }

    public boolean isOpenValidateCode() {
    return openValidateCode;
    }

    public void setOpenValidateCode(boolean openValidateCode) {
    this.openValidateCode = openValidateCode;
    }
    }

    UserDetailsService页面代码:


    package filter;

    import java.util.ArrayList;
    import java.util.Collection;

    import model.UserDetail;

    import org.springframework.dao.DataAccessException;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.GrantedAuthorityImpl;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.security.core.userdetails.UsernameNotFoundException;

    /**
    * 登录类
    *
    * @author Administrator
    * @comment 在这个类中,你就可以从数据库中读入用户的密码、角色信息、是否锁定、 账号是否过期等. new User()方法参数说明, String
    * username(用户名), String password(密码), boolean enabled(账户是否可用), boolean
    * accountNonExpired(账户是否未过期), boolean accountNonLocked(账户是否未锁定),
    * Collection<GrantedAuthority> authorities(账户所受权限).
    */
    public class MyUserDetailService implements UserDetailsService {


    @Override
    public UserDetails loadUserByUsername(String username)
    throws UsernameNotFoundException, DataAccessException {
    Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
    GrantedAuthorityImpl auth2 = new GrantedAuthorityImpl("ROLE_USER");// 进行授权
    auths.add(auth2);// 添加所授的权限
    UserDetail user = new UserDetail("123", "123", true, true, true, true, auths);
    return user;
    }
    }

    UserDetail类方法:


    package model;

    import java.util.Collection;

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

    @SuppressWarnings("serial")
    public class UserDetail implements UserDetails {
    private Collection<GrantedAuthority> authorities;
    private String password;
    private String username;
    private boolean isAccountNonExpired;
    private boolean isAccountNonLocked;
    private boolean isCredentialsNonExpired;
    private boolean isEnabled;

    /** default constructor */
    public UserDetail() {
    }

    public UserDetail(String username, String password,
    boolean isAccountNonExpired, boolean isAccountNonLocked,
    boolean isCredentialsNonExpired, boolean isEnabled, Collection<GrantedAuthority> authorities) {
    this.username = username;
    this.password = password;
    this.isAccountNonExpired = isAccountNonExpired;
    this.isAccountNonLocked = isAccountNonLocked;
    this.isCredentialsNonExpired = isCredentialsNonExpired;
    this.isEnabled = isEnabled;
    this.authorities = authorities;
    }

    // Constructors

    public Collection<GrantedAuthority> getAuthorities() {
    return authorities;
    }

    public void setAuthorities(Collection<GrantedAuthority> authorities) {
    this.authorities = authorities;
    }

    public String getPassword() {
    return password;
    }

    public void setPassword(String password) {
    this.password = password;
    }

    public String getUsername() {
    return username;
    }

    public void setUsername(String username) {
    this.username = username;
    }

    public boolean isAccountNonExpired() {
    return isAccountNonExpired;
    }

    public void setAccountNonExpired(boolean isAccountNonExpired) {
    this.isAccountNonExpired = isAccountNonExpired;
    }

    public boolean isAccountNonLocked() {
    return isAccountNonLocked;
    }

    public void setAccountNonLocked(boolean isAccountNonLocked) {
    this.isAccountNonLocked = isAccountNonLocked;
    }

    public boolean isCredentialsNonExpired() {
    return isCredentialsNonExpired;
    }

    public void setCredentialsNonExpired(boolean isCredentialsNonExpired) {
    this.isCredentialsNonExpired = isCredentialsNonExpired;
    }

    public boolean isEnabled() {
    return isEnabled;
    }

    public void setEnabled(boolean isEnabled) {
    this.isEnabled = isEnabled;
    }

    @Override
    public boolean equals(Object obj) {
    System.out.println("进入equals方法");
    if (obj instanceof UserDetail) {
    UserDetail another = (UserDetail)obj;
    return this.getUsername().equals(another.getUsername());
    }
    return super.equals(obj);
    }

    @Override
    public int hashCode() {
    System.out.println("进入hashCode方法");
    return this.getUsername().hashCode();
    }

    }

  • 相关阅读:
    nefu 628 Garden visiting
    codeforces 814 C. An impassioned circulation of affection 【尺取法 or DP】
    bzoj 2111: [ZJOI2010]Perm 排列计数 (dp+卢卡斯定理)
    Codeforces Round #423 (Div. 2)
    hdu 5955 Guessing the Dice Roll 【AC自动机+高斯消元】
    poj1322 Chocolate 【 概率DP 】
    poj 3414 Pots 【BFS+记录路径 】
    hdu5194 DZY Loves Balls 【概率论 or 搜索】
    51nod 1515 明辨是非 [并查集+set]
    hdu 1175 连连看 [DFS]
  • 原文地址:https://www.cnblogs.com/yanduanduan/p/5138378.html
Copyright © 2011-2022 走看看