测试用户
2023-04-13 43393f2bb11cbf9e6af40077bbc5284660e8a754
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
package com.common.security.configure;
 
import com.common.annotation.NoToken;
import com.common.core.utils.SpringContextUtils;
import com.common.filter.CorsFilter;
import com.common.filter.JwtAuthenticationTokenFilter;
import com.deloitte.system.model.AppConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.vote.AuthenticatedVoter;
import org.springframework.security.access.vote.UnanimousBased;
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.configuration.EnableWebSecurity;
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.web.access.expression.WebExpressionVoter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
 
import java.util.*;
import java.util.stream.Collectors;
 
/**
 * @author 廖振钦
 * @date 2022-01-14
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Autowired
    private RestfulAccessDeniedHandler restfulAccessDeniedHandler;
    @Autowired
    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
 
    // 放行所有请求
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = ((RequestMappingHandlerMapping)SpringContextUtils.getBean("requestMappingHandlerMapping")).getHandlerMethods();
        Set<String> anonymousUrls = new HashSet<>();
        for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethods.entrySet()) {
            // 获取所有接口的方法
            HandlerMethod handlerMethod = infoEntry.getValue();
            if (handlerMethod.hasMethodAnnotation(NoToken.class)) {
                PatternsRequestCondition requestCondition = infoEntry.getKey().getPatternsCondition();
                Optional.ofNullable(requestCondition).orElseThrow(RuntimeException::new);
                anonymousUrls.addAll(requestCondition.getPatterns().stream().map(m -> m).collect(Collectors.toList()));
            }
        }
 
        anonymousUrls.add("/druid/**");
 
 
        httpSecurity.csrf()
                .disable()
                .sessionManagement()// 基于token,所以不需要session
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers(HttpMethod.GET, // 允许对于网站静态资源的无授权访问
                        "/",
                        "/*.html",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js",
                        "/swagger-resources/**",
                        "/v2/api-docs/**",
                        "/druid/**"
                )
                .permitAll()
                .antMatchers(anonymousUrls.toArray(new String[0]))
                .anonymous()
                .anyRequest()// 除上面外的所有请求全部需要鉴权认证
                .authenticated()
                // 自定义accessDecisionManager
                .accessDecisionManager(accessDecisionManager());
                ;//放行option请求
        // 禁用缓存
        httpSecurity.headers().cacheControl();
        // 添加JWT filter
        httpSecurity.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        // 添加跨域 filter
        httpSecurity.addFilterBefore(corsFilter(), JwtAuthenticationTokenFilter.class);
        //添加自定义未授权和未登录结果返回
        httpSecurity.exceptionHandling()
                .accessDeniedHandler(restfulAccessDeniedHandler)
                .authenticationEntryPoint(restAuthenticationEntryPoint);
    }
 
    @Bean
    public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() {
        return new JwtAuthenticationTokenFilter();
    }
 
    @Bean
    public CorsFilter corsFilter() {
        return new CorsFilter();
    }
    @Bean
    public UserDetailsService userDetailsService() {
        //获取登录用户信息
        return username -> {
            AppConfig appConfig = AppConfig.dao.findByAppid(username);
            return new AppDetails(appConfig);
        };
    }
 
    @Bean
    public AccessDecisionManager accessDecisionManager() {
        List<AccessDecisionVoter<? extends Object>> decisionVoters
                = Arrays.asList(
                new WebExpressionVoter(),
                // new RoleVoter(),
                new RoleBasedVoter(),
                new AuthenticatedVoter());
        return new UnanimousBased(decisionVoters);
    }
}