spring security的ajax提交和json返回数据

版本一
ajax提交思想:用filter来实现,请求的匹配
json返回数据

public class LoginAuthenticationSuccesssHandler implements AuthenticationSuccessHandler {
    static final Logger logger = LogManager.getLogger(LoginAuthenticationSuccesssHandler.class.getName());
    private String defaultUrl;

    public void setDefaultUrl(String defaultUrl) {
        this.defaultUrl = defaultUrl;
    }

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException {
        response.setContentType("application/json; charset=UTF-8");
        ReturnEntity<String> returnEntity = new ReturnEntity<>();
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.writeValue(response.getWriter(), returnEntity);
    }

}

以后抽空完善具体代码,现在就说下核心思路

版本二

先直接上代码:
spring-security.xml的配置文件

<?xml version="1.0" encoding="UTF-8"?>
<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-4.2.xsd
                    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">

    <http pattern="/login/**" security="none"></http>
    <http auto-config="false" use-expressions="true" entry-point-ref="http403EntryPoint">
        <csrf disabled="true" />

        <!-- 退出 -->
        <logout invalidate-session="true" logout-url="/logout.do" logout-success-url="/index.html" delete-cookies="true" />

        <!-- session管理 -->
        <session-management invalid-session-url="/login/timedout.do" session-fixation-protection="none"
            session-authentication-error-url="/login/timedout.do">
            <concurrency-control error-if-maximum-exceeded="true" expired-url="/login/timedout.do"
                max-sessions="1" />
        </session-management>
        <!-- 拦截器 -->
        <custom-filter ref="CustomUsernamePasswordAuthenticationFilter" position="FORM_LOGIN_FILTER " />
        <access-denied-handler error-page="/accessDenied.htm" />
    </http>

    <!-- 权限管理器 -->
    <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref="userServiceDetail">
            <password-encoder ref="standardPasswordEncoder" />
        </authentication-provider>
    </authentication-manager>

    <beans:bean id="CustomUsernamePasswordAuthenticationFilter" class="u.frame.web.trade.security.ne.MyUsernamePasswordAuthenticationFilter">
        <beans:property name="authenticationManager" ref="authenticationManager" />
        <beans:property name="authenticationSuccessHandler" ref="customSuccessHandler" />
        <beans:property name="authenticationFailureHandler" ref="failureHandler" />
        <beans:property name="filterProcessesUrl" value="/j_spring_security_check.do" />
<!--        <beans:property name="usernameParameter" value="jsonUsername" /> -->
<!--        <beans:property name="passwordParameter" value="j_password" /> -->
    </beans:bean>

    <!-- 登录成功的处理 -->
    <beans:bean id="customSuccessHandler" class="u.frame.web.trade.security.ne.MySimpleUrlAuthenticationSuccessHandler">
        <beans:property name="defaultTargetUrl" value="/login.htm" />
        <beans:property name="targetUrlParameter" value="/LoginSuccessful.htm" />
    </beans:bean>

    <!-- 登录失败的处理 -->
    <beans:bean id="failureHandler" class="u.frame.web.trade.security.ne.MySimpleUrlAuthenticationFailureHandler">
        <beans:property name="defaultFailureUrl" value="/login.htm" />
    </beans:bean>

    <!-- 403的处理 -->
    <beans:bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />

    <!-- 获得用户信息 -->
    <beans:bean id="userServiceDetail" class="u.frame.web.trade.security.old.MyUserDetailServiceImpl" />

    <!-- 密码加密工具 -->
    <beans:bean id="standardPasswordEncoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder">
        <beans:constructor-arg value="q1w2e3r4t5y6u7i8o9" />
    </beans:bean>
</beans:beans>

MyUsernamePasswordAuthenticationFilter.java

package u.frame.web.trade.security.ne;

import java.io.BufferedReader;

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

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.fasterxml.jackson.databind.ObjectMapper;

import u.frame.web.trade.model.Login;

public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    private String jsonUsername;
    private String jsonPassword;

    @Override
    protected String obtainPassword(HttpServletRequest request) {
        String password = null;

        if (checkJson(request)) {
            password = this.jsonPassword;
        } else {
            password = super.obtainPassword(request);
        }

        return password;
    }

    @Override
    protected String obtainUsername(HttpServletRequest request) {
        String username = null;

        if (checkJson(request)) {
            username = this.jsonUsername;
        } else {
            username = super.obtainUsername(request);
        }

        return username;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
        if (checkJson(request)) {
            try {
                /*
                 * HttpServletRequest can be read only once
                 */
                StringBuffer sb = new StringBuffer();
                String line = null;

                BufferedReader reader = request.getReader();
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }

                // json transformation
                ObjectMapper mapper = new ObjectMapper();
                Login login = mapper.readValue(sb.toString(), Login.class);

                this.jsonUsername = login.getUserName();
                this.jsonPassword = login.getPassWord();
                return new UsernamePasswordAuthenticationToken(jsonUsername, jsonPassword);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return super.attemptAuthentication(request, response);
    }

    public boolean checkJson(HttpServletRequest request) {
        if ("application/json".equals(request.getHeader("Content-Type"))) {
            return true;
        }
        return false;

    }
}

MySimpleUrlAuthenticationSuccessHandler.java

package u.frame.web.trade.security.ne;

import java.io.IOException;

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

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;

public class MySimpleUrlAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth)
            throws IOException, ServletException {

        if ("application/json".equals(request.getHeader("Content-Type"))) {
            /*
             * USED if you want to AVOID redirect to LoginSuccessful.htm in JSON authentication
             */
            response.getWriter().print("{\"responseCode\":\"SUCCESS\"}");
            response.getWriter().flush();
        } else {
            super.onAuthenticationSuccess(request, response, auth);
        }
    }
}

MySimpleUrlAuthenticationFailureHandler.java

package u.frame.web.trade.security.ne;

import java.io.IOException;

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

import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;

public class MySimpleUrlAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
            throws IOException, ServletException {
        if ("application/json".equals(request.getHeader("Content-Type"))) {
            /*
             * USED if you want to AVOID redirect to LoginSuccessful.htm in JSON authentication
             */
            response.getWriter().print("{\"responseCode\":\"Failure\"}");
            response.getWriter().flush();
        } else {
            // TODO Auto-generated method stub
            super.onAuthenticationFailure(request, response, exception);
        }

    }

}

MyUserDetailServiceImpl.java

package u.frame.web.trade.security.old;

import java.util.HashSet;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.StandardPasswordEncoder;

import u.frame.web.trade.model.Login;

public class MyUserDetailServiceImpl implements UserDetailsService {
    static final Logger logger = LogManager.getLogger(MyUserDetailServiceImpl.class.getName());
    @Autowired
    private StandardPasswordEncoder standardPasswordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        if (StringUtils.isEmpty(username)) {
            throw new UsernameNotFoundException("用户名不可为空!");
        }
        //测试用的
        if (!"123".equals(username)) {
            throw new UsernameNotFoundException("error");
        }
        Login login = new Login();
        login.setUserName(username);
        login.setPassWord(standardPasswordEncoder.encode("123"));
        logger.info(username);

        boolean enabled = true;
        boolean accountNonExpired = true; 
        boolean credentialsNonExpired = true; 
        boolean accountNonLocked = true;

        Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
        return new org.springframework.security.core.userdetails.User(//
                login.getUserName(), //
                // user.getUserPassword()+"{"+user.getUserName()+"}",
                login.getPassWord(), //
                enabled, //
                accountNonExpired, //
                credentialsNonExpired, //
                accountNonLocked, //
                authorities//
        );
    }
}

思路来源于http://stackoverflow.com/questions/19500332/spring-security-and-json-authentication

整体思想,就是filter过滤拦截。

版本三
不多说,直接上代码
applicationContext-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<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-4.2.xsd
                    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">
    <!-- 不需要拦截 -->
    <http pattern="/login/**" security="none"></http>
    <http auto-config="false" use-expressions="true" entry-point-ref="http403EntryPoint">
        <csrf disabled="true" />
        <headers>
            <frame-options policy="SAMEORIGIN" />
            <cache-control disabled="true" />
            <content-type-options disabled="true" />
        </headers>
        <logout invalidate-session="true" logout-url="/login/logout.do" logout-success-url="/login/success.do" delete-cookies="true" />
        <session-management invalid-session-url="/login/timedout.do" session-fixation-protection="none"
            session-authentication-error-url="/login/timedout.do">
            <concurrency-control error-if-maximum-exceeded="false" expired-url="/login/timedout.do" max-sessions="1" />
        </session-management>
        <!-- filter_security_interceptor -->
        <custom-filter ref="mySecurityFilter" before="FILTER_SECURITY_INTERCEPTOR" />
        <!-- form_login_filter -->
        <custom-filter ref="CustomUsernamePasswordAuthenticationFilter" before="FORM_LOGIN_FILTER" />
    </http>

    <beans:bean id="CustomUsernamePasswordAuthenticationFilter" class="u.frame.web.trade.security.ne.MyUsernamePasswordAuthenticationFilter">
        <beans:property name="authenticationManager" ref="authenticationManager" />
        <beans:property name="authenticationSuccessHandler" ref="successHandler" />
        <beans:property name="authenticationFailureHandler" ref="failureHandler" />
        <beans:property name="filterProcessesUrl" value="/logincheck1.do" />
        <!-- <beans:property name="usernameParameter" value="jsonUsername" /> -->
        <!-- <beans:property name="passwordParameter" value="j_password" /> -->
    </beans:bean>

    <!-- 自定义过滤器 -->
    <beans:bean id="mySecurityFilter" class="u.frame.web.trade.security.old.MyFilterSecurityInterceptor" />

    <!-- =========== -->
    <!-- =========== -->
    <!-- =========== -->
    <!-- =========== -->
    <!-- =========== -->
    <!-- =========== -->
    <!-- =========== -->
    <!-- =========== -->

    <!-- 认证管理器 -->
    <!--验证配置,认证管理器,实现用户认证的入口,主要实现UserDetailsService接口即可 -->
    <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref="userServiceDetail">
            <password-encoder ref="standardPasswordEncoder" />
        </authentication-provider>
    </authentication-manager>

    <!-- 登录成功的处理 -->
    <beans:bean id="successHandler" class="u.frame.web.trade.security.ne.MySimpleUrlAuthenticationSuccessHandler">
        <beans:property name="defaultTargetUrl" value="/login/success.do" />
        <!-- <beans:property name="targetUrlParameter" value="/LoginSuccessful.htm" /> -->
    </beans:bean>

    <!-- 登录失败的处理 -->
    <beans:bean id="failureHandler" class="u.frame.web.trade.security.ne.MySimpleUrlAuthenticationFailureHandler">
        <beans:property name="defaultFailureUrl" value="/login/error.do" />
    </beans:bean>

    <!-- 403的处理 -->
    <beans:bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />

    <!-- 获得用户信息 -->
    <beans:bean id="userServiceDetail" class="u.frame.web.trade.security.old.MyUserDetailServiceImpl" />

    <!-- 密码加密工具 -->
    <beans:bean id="standardPasswordEncoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder">
        <beans:constructor-arg value="q1w2e3r4t5y6u7i8o9p0" />
    </beans:bean>
</beans:beans>

MyUsernamePasswordAuthenticationFilter.java

package u.frame.web.trade.security.ne;

import java.io.BufferedReader;
import java.io.IOException;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.fasterxml.jackson.databind.ObjectMapper;

import u.frame.web.trade.model.Login;

public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    static Log log = LogFactory.getLog(MySimpleUrlAuthenticationFailureHandler.class);
    // 用户的登录信息
    private Login login;

    @Override
    protected String obtainPassword(HttpServletRequest request) {
        System.out.println("MyUsernamePasswordAuthenticationFilter-obtainPassword");
        if (checkJson(request)) {
            if (login != null) {
                return login.getPassWord();
            }
        }
        // }
        return super.obtainPassword(request);
    }

    @Override
    protected String obtainUsername(HttpServletRequest request) {
        System.out.println("MyUsernamePasswordAuthenticationFilter-obtainUsername");
        if (checkJson(request)) {
            if (login != null) {
                return login.getUserName();
            }
        }
        return super.obtainUsername(request);
    }

    public boolean checkJson(HttpServletRequest request) {
        try {
            if ("application/json".equals(request.getHeader("Content-Type"))) {
                StringBuffer sb = new StringBuffer();
                String line = null;
                BufferedReader reader;
                reader = request.getReader();
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
                if (StringUtils.isNotEmpty(sb.toString())) {
                    ObjectMapper mapper = new ObjectMapper();
                    login = mapper.readValue(sb.toString(), Login.class);
                }
                return true;
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return false;

    }
}

思想来源:
http://docs.spring.io/spring-security/site/docs/3.0.x/reference/ns-config.html

说明:
这里写图片描述

简单的说,就是重写http/form-login,使用http/form-login的另一种形式UsernamePasswordAuthenticationFilter就可以了。

版本4

为了解决UsernameNotFoundException的异常抛出问题

直接上代码:
applicationContext-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-4.2.xsd
                    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">
    <!-- 不需要拦截 -->
    <security:http pattern="/login/**" security="none"></security:http>
    <security:http auto-config="false" use-expressions="true" entry-point-ref="http403EntryPoint">
        <security:csrf disabled="true" />
        <security:headers>
            <security:frame-options policy="SAMEORIGIN" />
            <security:cache-control disabled="true" />
            <security:content-type-options disabled="true" />
        </security:headers>
        <!-- 退出 -->
        <security:logout invalidate-session="true" logout-url="/login/logout.do" logout-success-url="/login/outSuccess.do"
            delete-cookies="true" />
        <!-- session超时 -->
        <security:session-management invalid-session-url="/login/timedout.do" session-fixation-protection="none"
            session-authentication-error-url="/login/timedout.do">
            <security:concurrency-control error-if-maximum-exceeded="false" expired-url="/login/timedout.do"
                max-sessions="1" />
        </security:session-management>
        <!-- filter_security_interceptor -->
        <security:custom-filter ref="mySecurityFilter" before="FILTER_SECURITY_INTERCEPTOR" />
        <!-- form_login_filter -->
        <security:custom-filter ref="CustomUsernamePasswordAuthenticationFilter" before="FORM_LOGIN_FILTER" />
    </security:http>

    <bean id="CustomUsernamePasswordAuthenticationFilter" class="u.frame.web.trade.security.MyUsernamePasswordAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="authenticationSuccessHandler" ref="successHandler" />
        <property name="authenticationFailureHandler" ref="failureHandler" />
        <property name="filterProcessesUrl" value="/logincheck.do" />
    </bean>

    <!-- 自定义过滤器 -->
    <bean id="mySecurityFilter" class="u.frame.web.trade.security.MyFilterSecurityInterceptor" />

    <!-- 认证管理器 -->
    <bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
        <constructor-arg>
            <list>
                <ref bean="daoAuthenticationProvider" />
            </list>
        </constructor-arg>
    </bean>
    <!-- 认证提供类 -->
    <bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
        <property name="userDetailsService" ref="userServiceDetail" />
        <property name="passwordEncoder" ref="standardPasswordEncoder" />
        <!--不隐藏错误-->
        <property name="hideUserNotFoundExceptions" value="false" />
    </bean>

    <!-- 登录成功的处理 -->
    <bean id="successHandler" class="u.frame.web.trade.security.MySimpleUrlAuthenticationSuccessHandler">
        <property name="defaultTargetUrl" value="/login/success.do" />
        <!-- <property name="targetUrlParameter" value="/LoginSuccessful.htm" /> -->
    </bean>

    <!-- 登录失败的处理 -->
    <bean id="failureHandler" class="u.frame.web.trade.security.MySimpleUrlAuthenticationFailureHandler">
        <property name="defaultFailureUrl" value="/login/error.do" />
    </bean>

    <!-- 403的处理 -->
    <bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />

    <!-- 获得用户信息 -->
    <bean id="userServiceDetail" class="u.frame.web.trade.security.MyUserDetailServiceImpl" />

    <!-- 密码加密工具 -->
    <bean id="standardPasswordEncoder" class="org.springframework.security.crypto.password.StandardPasswordEncoder">
        <constructor-arg value="q1w2e3r4t5y6u7i8o9" />
    </bean>
</beans>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值