forked from kidgrow-microservices-platform

zhaoxiaohao
2021-03-11 197ca341f4539eb3322b50a87a4073d5b138a12a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package com.kidgrow.oauth2.config;
 
import com.kidgrow.common.constant.SecurityConstants;
//import com.kidgrow.oauth2.handler.InMemoryAuthenticationProvider;
import com.kidgrow.oauth2.mobile.MobileAuthenticationSecurityConfig;
import com.kidgrow.oauth2.openid.OpenIdAuthenticationSecurityConfig;
import com.kidgrow.common.config.DefaultPasswordConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.header.HeaderWriterFilter;
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
 
import javax.annotation.Resource;
import java.util.Arrays;
 
 
/**
 * 石家庄喜高科技有限责任公司 版权所有 © Copyright 2020<br>
 *
 * @Description:  * spring security配置
 *  * 在WebSecurityConfigurerAdapter不拦截oauth要开放的资源<br>
 * @Project: <br>
 * @CreateDate: Created in 2020/2/20 09:19 <br>
 * @Author: <a href="4345453@kidgrow.com">liuke</a>
 */
@Configuration
@Import(DefaultPasswordConfig.class)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Autowired
    private AuthenticationSuccessHandler authenticationSuccessHandler;
    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;
 
    @Autowired(required = false)
    private AuthenticationEntryPoint authenticationEntryPoint;
 
    @Resource
    private UserDetailsService userDetailsService;
 
    @Autowired
    private PasswordEncoder passwordEncoder;
 
    @Resource
    private LogoutHandler oauthLogoutHandler;
 
    @Autowired
    private ValidateCodeSecurityConfig validateCodeSecurityConfig;
 
    @Autowired
    private OpenIdAuthenticationSecurityConfig openIdAuthenticationSecurityConfig;
 
    @Autowired
    private MobileAuthenticationSecurityConfig mobileAuthenticationSecurityConfig;
 
//    @Autowired
//    InMemoryAuthenticationProvider inMemoryAuthenticationProvider;
 
    /**
     * 这一步的配置是必不可少的,否则SpringBoot会自动配置一个AuthenticationManager,覆盖掉内存中的用户
     * @return 认证管理对象
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
//    @Bean
//    @Override
//    public AuthenticationManager authenticationManagerBean() throws Exception {
//        // 认证管理器中只提供我需要的两个第一个是自定义认证,第二个是数据库认证,需要经过两层认证才能通过,默认的
//
//        // 构造函数不提供自定义认证Provider,那么默认提供DaoAuthenticationProvider
//
//        ProviderManager authenticationManager = new ProviderManager(Arrays.asList(inMemoryAuthenticationProvider, daoAuthenticationProvider()));
//
//        // 不擦除认证密码,擦除会导致TokenBasedRememberMeServices因为找不到Credentials再调用UserDetailsService而抛出UsernameNotFoundException
//
//        authenticationManager.setEraseCredentialsAfterAuthentication(false);
//
//        return authenticationManager;
//    }
 
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                    .anyRequest()
                    //授权服务器关闭basic认证
                    .permitAll()
                    .and()
                .formLogin()
                    .loginPage(SecurityConstants.LOGIN_PAGE)
                    .loginProcessingUrl(SecurityConstants.OAUTH_LOGIN_PRO_URL)
                    .successHandler(authenticationSuccessHandler)
                    .failureHandler(authenticationFailureHandler)
                    .and()
                .logout()
                    .logoutUrl(SecurityConstants.LOGOUT_URL)
                    .logoutSuccessUrl(SecurityConstants.LOGIN_PAGE)
                    .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())
                    .addLogoutHandler(oauthLogoutHandler)
                    .clearAuthentication(true)
                    .and()
                .apply(validateCodeSecurityConfig)
                    .and()
                .apply(openIdAuthenticationSecurityConfig)
                    .and()
                .apply(mobileAuthenticationSecurityConfig)
                    .and()
                .csrf().disable()
                // 解决不允许显示在iframe的问题
                .headers().frameOptions().disable().cacheControl();
 
        // 基于密码 等模式可以无session,不支持授权码模式
        if (authenticationEntryPoint != null) {
            http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
            http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        } else {
            // 授权码模式单独处理,需要session的支持,此模式可以支持所有oauth2的认证
            http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
        }
    }
 
    /**
     * 全局用户信息
     */
    @Autowired
    public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
    }
}