• mark v1 SecurityConfig


    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(20);
    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(); } }
  • 相关阅读:
    SaaS模式应用之多租户系统开发(单数据库多Schema设计)
    web-api POST body object always null
    linq to js 用法
    c#导出数据到csv文本文档中,数据前面的0不见了解决方法
    金蝶BOS元模型分析
    DotNet 资源大全中文版
    JavaScript中的类方法、对象方法、原型方法
    解决System.Data.SqlClient.SqlException (0x80131904): Timeout 时间已到的问题
    在需要隐藏navigationController控制器
    升级macOS Sierra系统 导致错误 app: resource fork, Finder information, or similar detritus not allowed
  • 原文地址:https://www.cnblogs.com/xmanblue/p/6963782.html
Copyright © 2020-2023  润新知