亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot?Security從入門到實戰(zhàn)示例教程

 更新時間:2022年05月06日 09:52:32   作者:lakernote  
Spring?Security是一個功能強大且高度可定制的身份驗證和訪問控制框架,接下來通過本文給大家介紹SpringBoot?Security從入門到實戰(zhàn)示例教程,感興趣的朋友一起看看吧

前言

Spring Security是一個功能強大且高度可定制的身份驗證和訪問控制框架。提供了完善的認證機制和方法級的授權(quán)功能。是一款非常優(yōu)秀的權(quán)限管理框架。它的核心是一組過濾器鏈,不同的功能經(jīng)由不同的過濾器。這篇文章給大家講解SpringBoot Security從入門到實戰(zhàn),內(nèi)容如下所示:

入門

測試接口

假設我們用下面的接口做權(quán)限測試。

@RestController
public class LakerController {
    @GetMapping("/laker")
    public String laker() {
        return IdUtil.simpleUUID();
    }
    @GetMapping("/laker/q")
    public String lakerQ() {
        return IdUtil.simpleUUID();
    }
}

瀏覽器訪問:http://localhost:8080/laker,結(jié)果如下:

增加依賴

pom.xml,添加 spring-boot-starter-securtiy 依賴。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

再次訪問http://localhost:8080/laker,結(jié)果如下:

簡要解析

我們訪問http://localhost:8080/laker,security判斷我們沒有登錄,則會302重定向http://localhost:8080/login(默認)

  • security會返回一個默認的登錄頁。
  • 默認用戶名為:user,密碼在服務啟動時,會隨機生成一個,可以查看啟動日志如下:

2022-05-02 21:01:03.697  INFO 17896 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2022-05-02 21:01:03.825  INFO 17896 --- [           main] .s.s.UserDetailsServiceAutoConfiguration : 

Using generated security password: e53fef6a-3f61-43c3-9609-ce88fd7c0841

當然,可以通過配置文件設置默認的用戶名、密碼、角色。

spring:
  security:
    user:
      # 默認是 user
      name: laker
      password: laker
      roles:
        - ADMIN
        - TESTER

以上的默認都是可以修改的哈。

判斷是否登錄使用傳統(tǒng)的cookie session模式哈,JSESSIONID E3512CD1A81DB7F2144C577BA38D2D92 HttpOnly true

自定義配置

實際項目中我們的用戶、密碼、角色、權(quán)限、資源都是存儲在數(shù)據(jù)庫中的,我們可以通過自定義類繼承 WebSecurityConfigurerAdapter,從而實現(xiàn)對 Spring Security 更多的自定義配置。

@Configuration
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {
		...
}

配置密碼加密方式

必須配置,否則報空指針異常。

   @Bean
    PasswordEncoder passwordEncoder() {
        // 不加密
        return NoOpPasswordEncoder.getInstance();
    }

Spring Security 提供了多種密碼加密方案,官方推薦使用 BCryptPasswordEncoder

BCryptPasswordEncoder 使用 BCrypt 強哈希函數(shù),開發(fā)者在使用時可以選擇提供 strengthSecureRandom 實例。strength 取值在 4~31 之間(默認為 10)。strength 越大,密鑰的迭代次數(shù)越多(密鑰迭代次數(shù)為 2^strength)。如果是數(shù)據(jù)庫認證,庫里的密碼同樣也存放加密后的密碼。同一密碼每次 Bcrypt 生成的結(jié)果都會變化不會重復。

配置AuthenticationManagerBuilder 認證用戶、角色權(quán)限

支持直接配置內(nèi)存認證模式和配置UserDetailsServiceBean方式

內(nèi)存認證模式,實際項目不用這個哦。(僅做了解)

 /**
     * 配置用戶及其對應的角色
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("admin").password("123").roles("ADMIN", "USER")
                .and()
                .withUser("laker").password("123").roles("USER");
    }

上面在UserDetailsService的實現(xiàn)之一InMemoryUserDetailsManager中,即存儲在內(nèi)存中。

自定義UserDetailsServiceBean方式,實際項目都是使用這個,可定制化程度高。

步驟一:定義一個LakerUserService實現(xiàn)UserDetailsService,配置成SpringBean。該方法將在用戶登錄時自動調(diào)用。

@Service
public class LakerUserService implements UserDetailsService {
    @Autowired
    UserMapper userMapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // username 就是前端傳遞的例如 laker 123,即 laker
        User user = userMapper.loadUserByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("賬戶不存在!");
        }
        user.setAuthorities(...);
        return user;
    }
}

username

password(加密后的密碼)

authorities

返回的Bean中以上3個都不能為空。返回User后由系統(tǒng)提供的 DaoAuthenticationProvider 類去比對密碼是否正確。

Spring Security默認支持表單請求登錄的源碼,UsernamePasswordAuthenticationFilter.java

步驟二:在把自定義的LakerUserService裝載進去.

@Autowired
UserService userService;
...
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userService);
}

步驟三:其中我們的業(yè)務用戶User必須要實現(xiàn)UserDetails接口,并實現(xiàn)該接口中的 7 個方法:

  • getAuthorities():獲取當前用戶對象所具有的權(quán)限信息
  • getPassword():獲取當前用戶對象的密碼

返回的密碼和用戶輸入的登錄密碼不匹配,會自動拋出 BadCredentialsException 異常。

  • getUsername():獲取當前用戶對象的用戶名
  • isAccountNonExpired():當前賬戶是否未過期
  • isAccountNonLocked():當前賬戶是否未鎖定
  • 返回了 false,會自動拋出 AccountExpiredException 異常。
  • isCredentialsNonExpired():當前賬戶密碼是否未過期
  • isEnabled():當前賬戶是否可用
@Data
public class User implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    private Boolean enabled;
    private Boolean locked;
    private List<String> authorities;
    @Override
    public String getPassword() {
        return password;
    }
    @Override
    public String getUsername() {
        return username;
    }
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {
        return !locked;
    }
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    @Override
    public boolean isEnabled() {
        return enabled;
    }
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authoritiesList = new ArrayList<>();
        for (String authority : authorities) {
            authoritiesList.add(new SimpleGrantedAuthority(authority));
        }
        return authoritiesList;
    }
}

配置HttpSecurity Url訪問權(quán)限

  /**
     * 配置 URL 訪問權(quán)限
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //
        http    // 1.開啟 HttpSecurity 配置
                .authorizeRequests()
                // laker/** 模式URL必須具備laker.query
                .antMatchers("/laker/**").hasAnyAuthority("laker.query")
                // 用戶訪問其它URL都必須認證后訪問(登錄后訪問)
                .anyRequest().authenticated()
                .and()
                // 2.開啟表單登錄,前后端分離的時候不用這個
                .formLogin()
                // 未登錄時 重定向的url 默認是/login 內(nèi)置的頁面,可以自己自定義哈。一般前后端分離,不用這個
//                .loginPage("/login")
                //
//                .defaultSuccessUrl("/user",true)
//                .usernameParameter("username") // default is username
//                .passwordParameter("password") // default is password
//                .loginPage("/authentication/login") // default is /login with an HTTP get
//                .failureUrl("/authentication/login?failed") // default is /login?error
//                .loginProcessingUrl("/authentication/login/process") // default is /login
                .and()
                // 3.關(guān)閉csrf,前后端分離不需要這個。
                .csrf().disable();
                //授權(quán)碼模式需要 會彈出默認自帶的登錄框
                http.httpBasic();   
        		// 開啟注銷登錄的配置 
                http.logout()
                    // 配置注銷登錄請求URL為"/logout"(默認也就是 /logout)
                    .logoutSuccessUrl("/logout")
                    .clearAuthentication(true) // 清除身份認證信息
                    .invalidateHttpSession(true) // 使 session 失效;
    }
  • formLogin() 表示開啟表單登錄
  • **defaultSuccessUrl()**表示默認登錄驗證成功跳轉(zhuǎn)的url,默認重定向到上次訪問未成功的,如果沒有則重定向到/.
  • loginProcessingUrl() 方法配置登錄接口為“/login”,即可以直接調(diào)用“/login”接口,發(fā)起一個 POST 請求進行登錄,登錄參數(shù)中用戶名必須為 username,密碼必須為 password,配置 loginProcessingUrl 接口主要是方便 Ajax 或者移動端調(diào)用登錄接口。

    anyRequest          |   匹配所有請求路徑
    access              |   SpringEl表達式結(jié)果為true時可以訪問
    anonymous           |   匿名可以訪問 所有人都能訪問,但是帶上 token訪問后會報錯403
    denyAll             |   用戶不能訪問 所有人都能訪問,包括帶上 token 訪問
    fullyAuthenticated  |   用戶完全認證可以訪問(非remember-me下自動登錄)
    hasAnyAuthority     |   如果有參數(shù),參數(shù)表示權(quán)限,則其中任何一個權(quán)限可以訪問
    hasAnyRole          |   如果有參數(shù),參數(shù)表示角色,則其中任何一個角色可以訪問
    hasAuthority        |   如果有參數(shù),參數(shù)表示權(quán)限,則其權(quán)限可以訪問
    hasIpAddress        |   如果有參數(shù),參數(shù)表示IP地址,如果用戶IP和參數(shù)匹配,則可以訪問
    hasRole             |   如果有參數(shù),參數(shù)表示角色,則其角色可以訪問
    permitAll           |   用戶可以任意訪問
    rememberMe          |   允許通過remember-me登錄的用戶訪問
    authenticated       |   用戶登錄后可訪問

自定義successHandler

登錄成功后默認是重定向url,我們可以自定義返回json用于前后端分離場景以及其他邏輯,例如成功之后發(fā)短信等。

http.formLogin().successHandler((req, resp, authentication) -> {
    // 發(fā)短信哈
    Object principal = authentication.getPrincipal();
    resp.setContentType("application/json;charset=utf-8");
    PrintWriter out = resp.getWriter();
    out.write(new ObjectMapper().writeValueAsString(principal));
    out.flush();
    out.close();
})

自定義failureHandler

登錄失敗回調(diào)

http.formLogin().failureHandler((req, resp, e) -> {
    resp.setContentType("application/json;charset=utf-8");
    PrintWriter out = resp.getWriter();
    out.write(e.getMessage());
    out.flush();
    out.close();
})

自定義未認證處理

http.exceptionHandling()
.authenticationEntryPoint((req, resp, authException) -> {
            resp.setContentType("application/json;charset=utf-8");
            PrintWriter out = resp.getWriter();
            out.write("尚未登錄,請先登錄");
            out.flush();
            out.close();
        }
);

自定義權(quán)限不足處理

http.exceptionHandling()
				//沒有權(quán)限,返回json
				.accessDeniedHandler((request,response,ex) -> {
					response.setContentType("application/json;charset=utf-8");
					response.setStatus(HttpServletResponse.SC_FORBIDDEN);
					PrintWriter out = response.getWriter();
					Map<String,Object> map = new HashMap<String,Object>();
					map.put("code",403);
					map.put("message", "權(quán)限不足");
					out.write(objectMapper.writeValueAsString(map));
					out.flush();
					out.close();
				})

自定義注銷登錄

.logout()
.logoutUrl("/logout")
.logoutSuccessHandler((req, resp, authentication) -> {
    resp.setContentType("application/json;charset=utf-8");
    PrintWriter out = resp.getWriter();
    out.write("注銷成功");
    out.flush();
    out.close();
})

前后端分離場景

上面的都是入門的,實際項目中一般都是前后端分離的,在登錄時都是自定義登錄接口,例如登錄接口是restful風格,增加了其他的驗證碼參數(shù),還使用jwt來完成登錄鑒權(quán)等。

提供登錄接口

該接口需要在配置當中放行,未授權(quán)訪問需要授權(quán)的請求時,會返回401或者403狀態(tài)碼,前端可以根據(jù)這個進行路由提示處理。

@RestController
public class LoginController {
   @Autowired
   LoginService ...
   @PostMapping("/login")
   public  login(@RequestBody Login login){
       ...
       return token;
   }
}

Service層創(chuàng)建UsernamePasswordAuthenticationToken對象,把用戶名和密碼封裝成Authentication對象.

@Service
public class LoginServiceImpl implements LoginService {
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private UserDetailsService userDetailsService;
    @Override
    public  doLogin(Login login) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password;
        Authentication  authenticate
        try {         // 該方法會去調(diào)用UserDetailsServiceImpl.loadUserByUsername
             authenticate = authenticationManager.authenticate(authenticationToken);
        } catch (AuthenticationException e) {
            e.printStackTrace();
        }
 
        if (Objects.isNull(authenticate)) {
            //用戶名密碼錯誤
            throw new ServicesException(...);
        }
        User authUser = (User) authenticate.getPrincipal();
        String token = JwtUtil.createJWT(username);
        Map<String, String> map = new HashMap<>();
        map.put("token", token);
        return map;
    }
}

自定義認證過濾器

坊間有2種實現(xiàn)方式。

方式一:繼承UsernamePasswordAuthenticationFilter的寫法需要使用登陸成功處理器、失敗處理器等,還是需要按照security這一套來玩。

Spring Security默認支持表單請求登錄的源碼UsernamePasswordAuthenticationFilter.java

方式二:使用Filter的寫法沒有任何限制怎么玩都行,比如說添加其他參數(shù)驗證碼,返回json,token鑒權(quán)等。

@Component
public class LakerOncePerRequestFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws ServletException, IOException {
        String token = request.getHeader("Authorization");
        if (!StringUtils.isEmpty(token) )
        {
            // 校驗token ...
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user, null, authorities;
            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));                                     SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        }
        chain.doFilter(request, response);
    }
}                                                                                                           //3、在UsernamePasswordAuthenticationFilter前添加認證過濾器
http.addFilterBefore(lakerOncePerRequestFilter, UsernamePasswordAuthenticationFilter.class);

鑒權(quán)

1.注解鑒權(quán)

  • SpringSecurity配置類中開啟方法級的認證
  • 使用 @PreAuthorize注解在方法或者類
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {
...
@RestController
public class Controller {
    @GetMapping("/hello")
    @PreAuthorize("hasAnyAuthority('laker.query')")
    public String test() {
}

2.自定義Bean動態(tài)鑒權(quán)

因為@PreAuthorize支持SpringEL表達式,所以可以支持自定義SpringBean動態(tài)鑒權(quán)。

  • 先自定義一個SpringBean。
  • 使用 @PreAuthorize注解在方法或者類配合@PreAuthorize(“@rbacService.hasPermission(‘xx’)”)
@Component("rbacService")
public class LakerRBACService {
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        Object principal = authentication.getPrincipal();
        if (principal instanceof UserDetails) {
            UserDetails userDetails=(UserDetails)principal;

            /**
             * 該方法主要對比認證過的用戶是否具有請求URL的權(quán)限,有則返回true
             */
            //本次要訪問的資源
              SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(request.getMethod() + "" + request.getRequestURI());

            //用戶擁有的權(quán)限中是否包含請求的url
            return userDetails.getAuthorities().contains(simpleGrantedAuthority);
        }
        return false;
    }
        public boolean hasPermission() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Object principal = authentication.getPrincipal();
        if (principal instanceof UserDetails) {
            UserDetails userDetails = (UserDetails) principal;
            /**
             * 該方法主要對比認證過的用戶是否具有請求URL的權(quán)限,有則返回true
             */
            //本次要訪問的資源
            HttpServletRequest request =((ServletRequestAttributes)
                    RequestContextHolder.getRequestAttributes()).getRequest();

            SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(request.getRequestURI());
            //用戶擁有的權(quán)限中是否包含請求的url
            return userDetails.getAuthorities().contains(simpleGrantedAuthority);
        }
        return false;
    }
}
// controller方法
@PreAuthorize("@rbacService.hasPermission()")
public String test() {
}
// 或者高級的全局url鑒權(quán)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
         ...
      http.authorizeRequests() //設置授權(quán)請求,任何請求都要經(jīng)過下面的權(quán)限表達式處理
          .anyRequest().access("@rbacService.hasPermission(request,authentication)") //權(quán)限表達式     

3.擴展默認方法自定義擴展根對象SecurityExpressionRoot

http://chabaoo.cn/article/245172.htm

1.創(chuàng)建自定義根對象

public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {
    public CustomMethodSecurityExpressionRoot(Authentication authentication) {
        super(authentication);
    }
    /**
     * 自定義表達式
     * @param username 具有權(quán)限的用戶賬號
     */
    public boolean hasUser(String... username) {
        String name = this.getAuthentication().getName();
        HttpServletRequest request = ((ServletRequestAttributes)
                RequestContextHolder.getRequestAttributes()).getRequest();
        String[] names = username;
        for (String nameStr : names) {
            if (name.equals(nameStr)) {
                return true;
            }
        }
        return false;
    }
}

2.創(chuàng)建自定義處理器

創(chuàng)建自定義處理器,主要是重寫創(chuàng)建根對象的方法。

public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
    @Override
    protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation) {
        CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(authentication);
        root.setThis(invocation.getThis());
        root.setPermissionEvaluator(getPermissionEvaluator());
        root.setTrustResolver(getTrustResolver());
        root.setRoleHierarchy(getRoleHierarchy());
        root.setDefaultRolePrefix(getDefaultRolePrefix());
        return root;
    }
}

3.配置GlobalMethodSecurityConfiguration
之前我們使用@EnableGlobalMethodSecurity開啟全局方法安全,而這些全局方法級別的安全配置就在GlobalMethodSecurityConfiguration配置類中。

可以擴展這個類來自定義默認值,但必須確保在類上指定@EnableGlobalMethodSecurity 注解,否則會bean沖突報錯。

@Configuration
// 將EnableGlobalMethodSecurity注解移到這里
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return new CustomMethodSecurityExpressionHandler();
    }
}

4.controller使用自定義方法

@PreAuthorize("hasUser('laker','admin')")
public String test() {
    ...
}

登出

http.logout().logoutUrl("/logout").logoutSuccessHandler((request, response, authentication) -> {
            // 刪除用戶token
    		...
            // 返回json
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_OK);
            PrintWriter out = response.getWriter();
            out.write("OK");
            out.flush();
            out.close();
        });

跨域

@Override
protected void configure(HttpSecurity http) throws Exception {
	http.cors();//允許跨域,配置后SpringSecurity會自動尋找name=corsConfigurationSource的Bean
	http.csrf().disable();//關(guān)閉CSRF防御
}

@Configuration
public class CrosConfig {
    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration cores=new CorsConfiguration();
        cores.setAllowCredentials(true);//允許客戶端攜帶認證信息
        //springBoot 2.4.1版本之后,不可以用 * 號設置允許的Origin,如果不降低版本,則在跨域設置時使用setAllowedOriginPatterns方法
       // cores.setAllowedOrigins(Collections.singletonList("*"));//允許所有域名可以跨域訪問
        cores.setAllowedOriginPatterns(Collections.singletonList("*"));
        cores.setAllowedMethods(Arrays.asList("GET","POST","DELETE","PUT","UPDATE"));//允許哪些請求方式可以訪問
        cores.setAllowedHeaders(Collections.singletonList("*"));//允許服務端訪問的客戶端請求頭
        // 暴露哪些頭部信息(因為跨域訪問默認不能獲取全部頭部信息)
        cores.addExposedHeader(jsonWebTokenUtil.getHeader());
        // 注冊跨域配置
        // 也可以使用CorsConfiguration 類的 applyPermitDefaultValues()方法使用默認配置
        source.registerCorsConfiguration("/**",cores.applyPermitDefaultValues());
        return source;
    }
}

全局配置

@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public class SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Autowired
    UserService userService;

    @Autowired
    TokenFilter tokenFilter;

    /**
     * 配置 URL 訪問權(quán)限
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //
        http    // 1.過濾請求
                .authorizeRequests()
                // 2.對于登錄login 驗證碼captcha 允許訪問
                .antMatchers("/login").permitAll()
                // 用戶訪問其它URL都必須認證后訪問(登錄后訪問)
                .anyRequest().authenticated()
                .and()
                // 3.關(guān)閉csrf
                .csrf().disable()
                // 4.基于token,所以不需要session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                // 5.頁面能不能以 frame、 iframe、 object 形式嵌套在其他站點中,用來避免點擊劫持(clickjacking)攻擊
                .and().headers().frameOptions().disable();
        // 異常處理
        http.exceptionHandling()
                // 未認證返回401
                .authenticationEntryPoint((req, response, authException) -> {
                    response.setContentType("application/json;charset=utf-8");
                    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                    PrintWriter out = response.getWriter();
                    out.write("尚未登錄,請先登錄");
                    out.flush();
                    out.close();
                })
                // 沒有權(quán)限,返回403 json
                .accessDeniedHandler((request, response, ex) -> {
                    response.setContentType("application/json;charset=utf-8");
                    response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                    PrintWriter out = response.getWriter();
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("code", 403);
                    map.put("message", "權(quán)限不足");
                    out.write(JSONUtil.toJsonPrettyStr(map));
                    out.flush();
                    out.close();
                });
        // 配置登出
        http.logout().logoutUrl("/logout").logoutSuccessHandler((request, response, authentication) -> {
                // 刪除用戶token
            response.setContentType("application/json;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_OK);
            PrintWriter out = response.getWriter();
            out.write("OK");
            out.flush();
            out.close();
        });
        // 添加JWT filter
        http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class);
    }

    /**
     * 配置用戶及其對應的角色
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
    }
    /**
     * 適用于靜態(tài)資源的防攔截,css、js、image 等文件
     * 配置的url不會保護它們免受CSRF、XSS、Clickjacking等的影響。
     * 相反,如果您想保護端點免受常見漏洞的侵害,請參閱configure(HttpSecurity)
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/css/**", "/js/**");
    }
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    /**
     * 解決 無法直接注入 AuthenticationManager
     *
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception
    {
        return super.authenticationManagerBean();
    }
}

參考:

https://blog.csdn.net/X_lsod/article/details/122914659

https://blog.csdn.net/godleaf/article/details/108318403

https://blog.csdn.net/qq_43437874/article/details/119543579

到此這篇關(guān)于SpringBoot Security從入門到實戰(zhàn)示例教程的文章就介紹到這了,更多相關(guān)SpringBoot Security入門內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java 抽象類與接口的區(qū)別介紹

    java 抽象類與接口的區(qū)別介紹

    這篇文章主要介紹了java 抽象類與接口的區(qū)別介紹的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • Java超詳細精講數(shù)據(jù)結(jié)構(gòu)之bfs與雙端隊列

    Java超詳細精講數(shù)據(jù)結(jié)構(gòu)之bfs與雙端隊列

    廣搜BFS的基本思想是: 首先訪問初始點v并將其標志為已經(jīng)訪問。接著通過鄰接關(guān)系將鄰接點入隊。然后每訪問過一個頂點則出隊。按照順序,訪問每一個頂點的所有未被訪問過的頂點直到所有的頂點均被訪問過。廣度優(yōu)先遍歷類似與層次遍歷
    2022-07-07
  • java獲取包下被指定注解的類過程解析

    java獲取包下被指定注解的類過程解析

    這篇文章主要介紹了java獲取包下被指定注解的類過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-10-10
  • Java的JSON轉(zhuǎn)換類庫GSON的基礎使用教程

    Java的JSON轉(zhuǎn)換類庫GSON的基礎使用教程

    GSON是谷歌開源的一款Java對象與JSON對象互相轉(zhuǎn)換的類庫,Java的JSON轉(zhuǎn)換類庫GSON的基礎使用教程,需要的朋友可以參考下
    2016-06-06
  • Java?設計模式以虹貓藍兔的故事講解單例模式

    Java?設計模式以虹貓藍兔的故事講解單例模式

    單例模式(Singleton?Pattern)是?Java?中最簡單的設計模式之一。這種類型的設計模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式
    2022-03-03
  • Java實現(xiàn)連連看算法

    Java實現(xiàn)連連看算法

    這篇文章主要為大家詳細介紹了Java實現(xiàn)連連看算法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-06-06
  • Java 使用JdbcTemplate 中的queryForList發(fā)生錯誤解決辦法

    Java 使用JdbcTemplate 中的queryForList發(fā)生錯誤解決辦法

    這篇文章主要介紹了Java 使用JdbcTemplate 中的queryForList發(fā)生錯誤解決辦法的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • Spring?@DateTimeFormat日期格式化時注解場景分析

    Spring?@DateTimeFormat日期格式化時注解場景分析

    這篇文章主要介紹了Spring?@DateTimeFormat日期格式化時注解場景分析,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-05-05
  • Spring中緩存注解@Cache的使用詳解

    Spring中緩存注解@Cache的使用詳解

    這篇文章主要介紹了Spring中緩存注解@Cache的使用詳解,使用注解對數(shù)據(jù)進行緩存功能的框架,只需要簡單地加一個注解,就能實現(xiàn)緩存功能,大大簡化我們在業(yè)務中操作緩存的代碼,需要的朋友可以參考下
    2023-07-07
  • Java通過工廠、Map容器創(chuàng)建對象的方法

    Java通過工廠、Map容器創(chuàng)建對象的方法

    這篇文章主要介紹了Java通過工廠、Map容器創(chuàng)建對象的方法,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03

最新評論