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

来源:互联网 发布:神机妙算软件定额安装 编辑:程序博客网 时间:2024/06/13 19:07

版本一
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 0