1. 程式人生 > >Spring Security + JWT 實現基於Token的安全驗證

Spring Security + JWT 實現基於Token的安全驗證

@Configuration
@EnableWebSecurity
//新增annotation 支援,包括(prePostEnabled,securedEnabled...)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private UserDetailsService userDetailsService;


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.
                // 由於使用的是JWT,我們這裡不需要csrf
                csrf().disable()

                // 基於token,所以不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()

                //所有使用者可以訪問"/resources"目錄下的資源以及訪問"/home"和favicon.ico
                .antMatchers("/resources/**", "/home","/**/favicon.ico","/auth/*").permitAll()

                //以"/admin"開始的URL,並需擁有 "ROLE_ADMIN" 角色許可權,這裡用hasRole不需要寫"ROLE_"字首;
                .antMatchers("/admin/**").hasRole("ADMIN")
                //以"/admin"開始的URL,並需擁有 "ROLE_ADMIN" 角色許可權和 "ROLE_DBA" 角色,這裡不需要寫"ROLE_"字首;
                .antMatchers("/dba/**").access("hasRole('ADMIN') and hasRole('DBA')")

                //前面沒有匹配上的請求,全部需要認證;
                .anyRequest().authenticated()

                .and()
                //指定登入介面,並且設定為所有人都能訪問;
                .formLogin().loginPage("/login").permitAll()
                //如果登入失敗會跳轉到"/hello"
                .successForwardUrl("/hello")
                .successHandler(loginSuccessHandler())
                //如果登入失敗會跳轉到"/logout"
                //.failureForwardUrl("/logout")

                .and()
                .logout()
                .logoutUrl("/admin/logout") //指定登出的地址,預設是"/logout"
                .logoutSuccessUrl("/home")   //登出後的跳轉地址login?logout
                 //自定義LogoutSuccessHandler,在登出成功後呼叫,如果被定義則logoutSuccessUrl()就會被忽略
                .logoutSuccessHandler(logoutSuccessHandler())
                .invalidateHttpSession(true)  //定義登出時是否invalidate HttpSession,預設為true
                //.addLogoutHandler(logoutHandler) //新增自定義的LogoutHandler,預設會新增SecurityContextLogoutHandler
                .deleteCookies("usernameCookie","urlCookie") //在登出同時清除cookies
                ;

        // 禁用快取
        http.headers().cacheControl();

        // 新增JWT filter
        http.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);

    }

    @Autowired
    public void configureAuthentication(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
        authenticationManagerBuilder
                // 設定UserDetailsService
                .userDetailsService(this.userDetailsService)
                // 使用MD5進行密碼的加密
                .passwordEncoder(passwordEncoder());
    }

    private Md5PasswordEncoder passwordEncoder() {
        return new Md5PasswordEncoder();
    }


    private AccessDeniedHandler accessDeniedHandler(){
        AccessDeniedHandlerImpl handler = new AccessDeniedHandlerImpl();
        handler.setErrorPage("/login");
        return handler;
    }

    @Bean
    public JwtAuthenticationTokenFilter authenticationTokenFilterBean() throws Exception {
        return new JwtAuthenticationTokenFilter();
    }


    @Bean
    public LoginSuccessHandler loginSuccessHandler(){
        LoginSuccessHandler handler = new LoginSuccessHandler();
        return  handler;
    }

    @Bean
    public LogoutSuccessHandler logoutSuccessHandler(){
        return  new LogoutSuccessHandler();
    }
}