package cn.efunbox.cms.configuration;

import cn.efunbox.afw.core.entity.ApiCode;
import cn.efunbox.afw.core.entity.ApiResult;
import cn.efunbox.cms.code.CmsWebApiCode;
import cn.efunbox.cms.interceptor.LoginInterceptor;
import cn.efunbox.cms.security.CmsAuthenticationProvider;
import cn.efunbox.cms.security.CmsUserDetailsService;
import cn.efunbox.web.common.util.HttpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.SecurityProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import org.springframework.security.web.authentication.session.*;
import org.springframework.security.web.csrf.CsrfToken;
import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.security.web.session.ConcurrentSessionFilter;
import org.springframework.security.web.session.SessionManagementFilter;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.WebUtils;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * 安全配置中心
 * @author by tomas
 * @date 2017-06-06 15:30:00
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)//允许进入页面方法前检验
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

private static final Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);

 @Bean
 public UserDetailsService userDetailsService() {
return new CmsUserDetailsService();
 }

@Bean
 public CmsAuthenticationProvider cmsAuthenticationProvider() {
return new CmsAuthenticationProvider();
 }

/**
 * 设置那些 URL 忽略权限
 * @param web
 * @throws Exception
 */
 @Override
 public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
 web.ignoring().antMatchers(HttpMethod.GET,"/login/**");
 }

@Override
 protected void configure(HttpSecurity http) throws Exception {

http
.authorizeRequests()
.anyRequest().authenticated()
//先去掉 csrf
 .and().csrf().disable()
//.and().csrf().ignoringAntMatchers("/login","/logout").csrfTokenRepository(csrfTokenRepository()).and()
 .addFilterAfter(csrfHeaderFilter(), SessionManagementFilter.class)
.authorizeRequests().antMatchers("/login").permitAll();

 http
.formLogin().successHandler(new RestAuthenticationSuccessHandler())
.failureHandler(new RestAuthenticationFailureHandler())
.permitAll()
.and()
.logout().logoutSuccessHandler(new RestLogoutSuccessHandler())
.deleteCookies("JSESSIONID", "X-XSRF-TOKEN")
.permitAll();

 http.sessionManagement()
.sessionAuthenticationStrategy(sessionAuthenticationStrategy())
.and()
.addFilter(concurrentSessionFilter());

 http.exceptionHandling().authenticationEntryPoint(new RestAuthenticationEntryPoint());
// http
// .rememberMe()
// .rememberMeCookieName("")
// .tokenValiditySeconds(200000)
// .rememberMeServices(rememberMeServices);

 }

/**
 * 自定义 认证密码 和 获取用户 服务
 * @param auth
 * @throws Exception
 */
 @Autowired
 public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(cmsAuthenticationProvider())
.userDetailsService(userDetailsService());
 }

@Bean
 public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
 }

/**
 * csrf 过滤器 请求必须
 * @return
 */
 private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {

@Override
 protected void doFilterInternal(HttpServletRequest request,
 HttpServletResponse response,
 FilterChain filterChain) throws ServletException, IOException {

CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
 if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
 String token = csrf.getToken();
 if (cookie == null || token != null
 && !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
 cookie.setPath("/");
 response.addCookie(cookie);
 }
}
filterChain.doFilter(request, response);
 }
};
 }
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
 repository.setHeaderName("X-XSRF-TOKEN");//repository.setSessionAttributeName(("X-XSRF-TOKEN"));
 return repository;
 }

/**
 * 注册自定义的SessionRegistry
 */
 @Bean
 public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
 }

/**
 * 注册自定义 sessionAuthenticationStrategy
 * 设置 ConcurrentSessionControlAuthenticationStrategy 控制并发
 * 设置 SessionFixationProtectionStrategy 可以防盗session
 * 设置 RegisterSessionAuthenticationStrategy 触发了注册新sessin
 */
 @Bean
 public CompositeSessionAuthenticationStrategy sessionAuthenticationStrategy() {
ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlAuthenticationStrategy = new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry());
 concurrentSessionControlAuthenticationStrategy.setMaximumSessions();
 concurrentSessionControlAuthenticationStrategy.setExceptionIfMaximumExceeded(true);
 SessionFixationProtectionStrategy sessionFixationProtectionStrategy = new SessionFixationProtectionStrategy();
 RegisterSessionAuthenticationStrategy registerSessionStrategy = new RegisterSessionAuthenticationStrategy(sessionRegistry());
 CompositeSessionAuthenticationStrategy sessionAuthenticationStrategy = new CompositeSessionAuthenticationStrategy(
Arrays.asList(concurrentSessionControlAuthenticationStrategy, sessionFixationProtectionStrategy, registerSessionStrategy));
 return sessionAuthenticationStrategy;
 }

/**
 * 注册并发Session Filter
 */
 @Bean
 public ConcurrentSessionFilter concurrentSessionFilter() {
return new ConcurrentSessionFilter(sessionRegistry(), "/login?expired");
 }

/**
 * Rest 登陆成功后的处理
 */
 public class RestAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
@Override
 public void onAuthenticationSuccess(HttpServletRequest request,
 HttpServletResponse response, Authentication authentication)
throws ServletException, IOException {
HttpUtil.responseOutWithJson(request,response, ApiResult.ok(authentication.getPrincipal()));
 clearAuthenticationAttributes(request);
 }
}

/**
 * Rest 登录认证失败后的处理
 */

 public class RestAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
@Override
 public void onAuthenticationFailure (HttpServletRequest request, HttpServletResponse response, AuthenticationException exception)
throws ServletException, IOException {

logger.error("登录失败 exception={}" ,exception);
 saveException(request, exception);
 //密码错误
 if(exception instanceof BadCredentialsException){
HttpUtil.responseOutWithJson(request,response, ApiResult.error(CmsWebApiCode.PASSWORD_ERROR));
 }
//查询用户出错
 else if(exception instanceof UsernameNotFoundException){
HttpUtil.responseOutWithJson(request,response, ApiResult.error(CmsWebApiCode.USERNAME_PASSWORD_ERROR));
 }
//查询用户出错
 else if(exception instanceof SessionAuthenticationException){
HttpUtil.responseOutWithJson(request,response, ApiResult.error(CmsWebApiCode.MAX_COUNT_SESSION_ERROR));
 }
else {
HttpUtil.responseOutWithJson(request,response, ApiResult.error(CmsWebApiCode.AUTHORIZED_FAILD));
 }
}
}

/**
 * Rest 登出成功后的处理
 */

 public class RestLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
@Override
 public void onLogoutSuccess(HttpServletRequest request,
 HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
logger.info("登出成功! ");
 if (!StringUtils.isEmpty(request.getRequestedSessionId())){
//sessionRegistry().removeSessionInformation(request.getRequestedSessionId());
 if(null!=authentication && null!=authentication.getDetails() && null!=authentication.getPrincipal()){
List<SessionInformation> sessionInformations= sessionRegistry().getAllSessions(authentication.getPrincipal(),false);
 for (SessionInformation sessionInformation : sessionInformations) {
sessionInformation.expireNow();
 }
sessionRegistry().getAllPrincipals().remove(authentication.getDetails());
 }
}
HttpUtil.delCookies(request,response,"JSESSIONID", "X-XSRF-TOKEN");
 HttpUtil.responseOk(request,response);

 }
}

/**
 * Rest 权限不通过的处理
 */
 public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
 public void commence(HttpServletRequest request,
 HttpServletResponse response,
 AuthenticationException authException) throws IOException {
//原生返回 response.sendError(HttpServletResponse.SC_UNAUTHORIZED,"Authentication Failed: " + authException.getMessage());
 //cookie失效
 if(authException instanceof InsufficientAuthenticationException){
HttpUtil.responseOutWithJson(request,response, ApiResult.error(CmsWebApiCode.INVALID_COOKIE));
 }
HttpUtil.responseApiCode(request,response, ApiCode.ACCESS_DENIED);
 }
}
}
http://git.oschina.net/xiangxik/castle-platform/blob/master/castle-sample/castle-sample-console/src/main/java/com/whenling/sample/security/MainWebSecurityConfigBean.java
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
publicclassMainWebSecurityConfigBeanextendsWebSecurityConfigurerAdapter{
@Value("${security.skip_auth_urls?:/assets/**,/captcha**,/upload/**}")
privateString[]skipAuthUrls;
@Autowired
privateObjectFactoryobjectMapper;
@Autowired
privateObjectFactorymessageSourceAccessor;
publicMainWebSecurityConfigBean(){
super(true);
}
@Override
protectedvoidconfigure(HttpSecurityhttp)throwsException{
http.csrf().and().addFilter(newWebAsyncManagerIntegrationFilter()).exceptionHandling().and().headers().and().sessionManagement().and()
.securityContext().and().requestCache().and().anonymous().and().servletApi().and().logout();
http.getSharedObject(AuthenticationManagerBuilder.class)// .authenticationProvider(null)

.authenticationEventPublisher(defaultAuthenticationEventPublisher());
http.rememberMe().userDetailsService(userDetailsService());
FormLoginConfigurerconfigurer=http.headers().frameOptions().sameOrigin().and().csrf().disable().formLogin();
configurer.successHandler(newResultAuthenticationSuccessHandler(objectMapper.getObject()))
.failureHandler(newResultAuthenticationFailureHanlder(objectMapper.getObject(),messageSourceAccessor.getObject()));
ExceptionHandlingConfigurerexceptionConfigurer=configurer.permitAll().and().authorizeRequests().antMatchers(skipAuthUrls)
.permitAll().anyRequest().authenticated().and().exceptionHandling();
exceptionConfigurer.authenticationEntryPoint(
newExceptionAuthenticationEntryPoint(newHttp403ForbiddenEntryPoint(),newLoginUrlAuthenticationEntryPoint("/login")));
exceptionConfigurer.and().logout().logoutSuccessUrl("/login").permitAll();
}
@Bean
publicUserDetailsServiceuserDetailsService(){
returnnewAdminDetailsService();
}
@Bean
publicDefaultAuthenticationEventPublisherdefaultAuthenticationEventPublisher(){
returnnewDefaultAuthenticationEventPublisher();
}
}

mark v1 SecurityConfig的更多相关文章

  1. [HNOI2019]校园旅行(构造+生成树+动规)

    题目 [HNOI2019]校园旅行 做法 最朴素的做法就是点对扩展\(O(m^2)\) 发现\(n\)比较小,我们是否能从\(n\)下手减少边数呢?是肯定的 单独看一个颜色的联通块,如果是二分图,我们 ...

  2. Mina工具类v1.5

    package com.cucpay.fundswap.util; import java.net.InetSocketAddress; import java.nio.charset.Charset ...

  3. 使用升级版的 Bootstrap typeahead v1.2.2

    上次介绍了 Bootstrap 2 中附带的 typeahead,功能强大,但是使用起来不太方便,作者 Terry Rosen 已经升级了一个新版本 v1.2.2,作出了很大的改进. 下载地址 htt ...

  4. [iOS UI进阶 - 2.0] 彩票Demo v1.0

    A.需求 1.模仿“网易彩票”做出有5个导航页面和相应功能的Demo 2.v1.0 版本搭建基本框架   code source:https://github.com/hellovoidworld/H ...

  5. 《Ruby语言入门教程v1.0》学习笔记-01

    <Ruby语言入门教程v1.0> 编著:张开川 邮箱:kaichuan_zhang@126.com 想要学习ruby是因为公司的自动化测试使用到了ruby语言,但是公司关于ruby只给了一 ...

  6. 名片管理系统v1.1(main)

    # version: 1.1# author: Mark import cords_tools while True: # 显示界面    cords_tools.show_cords() cords ...

  7. 开源项目——小Q聊天机器人V1.0

    小Q聊天机器人V1.0 http://blog.csdn.net/baiyuliang2013/article/details/51386281 小Q聊天机器人V1.1 http://blog.csd ...

  8. Ubuntu16.04搭建kubernetes v1.11.2集群

    1.节点介绍         master      cluster-1      cluster-2      cluster-3 hostname        k8s-55      k8s-5 ...

  9. 使用kubeadm安装Kubernetes v1.10

    关于K8S: Kubernetes是Google开源的容器集群管理系统.它构建于docker技术之上,为容器化的应用提供资源调度.部署运行.服务发现.扩 容缩容等整一套功能,本质上可看作是基于容器技术 ...

随机推荐

  1. hdu4445 CRAZY TANK 2012金华赛区现场赛D题

    简单推下物理公式  对角度枚举 物理公式不会推啊智商捉急啊.... 到现在没想通为什么用下面这个公式就可以包括角度大于90的情况啊... #include<iostream> #inclu ...

  2. C#中有关资源、BeginInvoke, Invoke和事件的事情

    事情是这么来的,我开发的一个程序报了一个错误 “在创建窗口句柄之前,不能在控件上调用 Invoke 或 BeginInvoke错误”. 然后我在网上查资料,发现一个有意思的问题,文章出处为“在创建窗口 ...

  3. Java对象引用传递探索

    一直认为自己对对象传递理解的颇为深刻,没想到最近一次的编码中,就犯下了这样的错误,令自己排查了很久才找到问题的根源, 辅以小case记录以自省. 代码如下: public class ObjRefer ...

  4. 【jQuery】remove()和empty()的使用

    在项目需求中 ,会涉及,为select下拉框中重新填充或追加新的下拉项. 这样的话 之前的下拉项就需要清除掉. 有了这个需求,就需要我们注意到remove()和empty()的区别在哪里: empty ...

  5. vc listview 大图标间距设置

    SendMessage(this.listViewChart.Handle,   LVM_SETICONSPACING,   0,   0x10000   *   140   +   130); 其中 ...

  6. Android(安卓)开发通过NDK调用JNI,使用opencv做本地c++代码开发配置方法 边缘检测 范例代码

    以前写过两个Android开发配置文档,使用NDK进行JNI开发,这样能够利用以前已经写好的C++代码. 前两篇博客地址: http://blog.csdn.net/watkinsong/articl ...

  7. Java设计模式之生产者消费者模式

    Java设计模式之生产者消费者模式 博客分类: 设计模式 设计模式Java多线程编程thread 转载 对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一 ...

  8. ionic新手教程第八课-(加更)从无到有说Ionic、绘图说明MVC-U-S

    这节课的内容,有些前面几节已经说过了. 公司这次给我一个任务,让我带一个没有编程基础的同事学习ionic. 今天是我跟他讲的第一课,晚上把讲的笔记整理了一下,认为还是挺适合零基础的朋友学习的. 有些前 ...

  9. 神奇的container_of

    container_of是linux内核中常用的一个宏,这个宏的功能是,根据某个结构体字段的指针,找到对应的结构体指针. 话不多说,先上源码: /** * container_of - cast a ...

  10. function/bind

    1.函数指针指向一类函数,这类函数的类型一样,也就是函数的返回类型和形参表一样. 2.不同的函数类型要使用不同的函数指针,才能指向它,有没有好的办法呢? 类比思考下,交换方法,对不同的类型要写不同的s ...