<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] # 1. 認證實現 登錄成功、登錄失敗、登出成功的處理。 <br/> 首先要明白一點,我們不需要自己寫登錄登出的 controller 層,Spring Security 已經幫我們封裝好了。登錄地址默認為`POST /login`,登出默認為`GET /logout`。 <br/> 步驟如下: **1. 實現登錄成功處理器接口AuthenticationSuccessHandler** ```java @Component public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth) throws IOException, ServletException { //可以獲取登錄成功后的賬號實體User User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); Map<String, Object> map = new HashMap<>(16); map.put("code", 2000); map.put("message", "登錄成功!"); map.put("user", user); response.setContentType("text/json;charset=utf-8"); response.getWriter().write(JSON.toJSONString(map)); } } ``` **2. 實現登錄失敗處理器接口AuthenticationFailureHandler** ```java @Component public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException ex) throws IOException, ServletException { Map<String, Object> map = new HashMap<>(16); //根據拋出不同異常來判斷賬號的狀態 if (ex instanceof AccountExpiredException) { map.put("code", 1000); map.put("message", "賬號過期"); } if (ex instanceof BadCredentialsException) { map.put("code", 1001); map.put("message", "密碼錯誤"); } if (ex instanceof CredentialsExpiredException) { map.put("code", 1002); map.put("message", "密碼過期"); } if (ex instanceof DisabledException) { map.put("code", 1003); map.put("message", "賬號不可用"); } if (ex instanceof LockedException) { map.put("code", 1004); map.put("message", "賬號鎖定"); } if (ex instanceof InternalAuthenticationServiceException) { map.put("code", 1005); map.put("message", "用戶不存在"); } if (map.get("code") == null) { map.put("code", 1006); map.put("message", "未知錯誤"); } response.setContentType("text/json;charset=utf-8"); response.getWriter().write(JSON.toJSONString(map)); } } ``` **3. 實現登出成功處理器接口LogoutSuccessHandler** ```java @Component public class CustomLogoutSuccessHandler implements LogoutSuccessHandler { @Override public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth) throws IOException, ServletException { Map<String, Object> map = new HashMap<>(16); map.put("code", 2000); map.put("message", "退出成功"); response.setContentType("text/json;charset=utf-8"); response.getWriter().write(JSON.toJSONString(map)); } } ``` **4. 將上面的處理器注冊** ```java @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { private CustomAuthenticationSuccessHandler authenticationSuccessHandler; @Autowired private CustomAuthenticationFailureHandler authenticationFailureHandler; @Autowired private CustomLogoutSuccessHandler logoutSuccessHandler; @Override protected void configure(HttpSecurity http) throws Exception { ... http.formLogin() .permitAll() .successHandler(authenticationSuccessHandler) .failureHandler(authenticationFailureHandler); http.logout() .permitAll() .logoutSuccessHandler(logoutSuccessHandler) .deleteCookies("JSESSIONID"); } ... } ``` **5. 演示** 經過用 postman 演示,登錄登出可以正常完成了。 <br/> # 2. 賬號不存在與密碼錯誤返回同一個異常問題 **1. 問題描述** 我用的 Spring Security 版本如下。 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <version>2.3.12.RELEASE</version> </dependency> ``` 不知道是 Spring Security 這樣設計有什么目的,還是一個 BUG,那就是無論是賬號不存在,或者密碼錯誤,登錄失敗處理器 AuthenticationFailureHandler 都統一返回密碼錯誤異常 BadCredentialsException。按照上面的代碼編寫則不論是賬號不存在,還是密碼錯誤,返回的 json 字符串始終如下。 ```json { "code": 1001, "message": "密碼錯誤" } ``` <br/> **2. 原因** (1)認證邏輯接口 UserDetailsService 默認拋出的異常為 UsernameNotFoundException。 ```java @Service public class LoginServiceImpl implements UserDetailsService { @Autowired private AccountService accountService; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { //根據username查詢數據庫 Account account = accountService.findByUsername(username); if (account == null) { throw new UsernameNotFoundException("用戶名不存在!"); } //用戶權限 List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("admin"); return new User(username, account.getPassword(), authorities); } } ``` (2)`this.hideUserNotFoundExceptions`默認為`true`。 ```java /** org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider **/ public abstract class AbstractUserDetailsAuthenticationProvider implements AuthenticationProvider,... { public Authentication authenticate(Authentication authentication) throws AuthenticationException { ... if (user == null) { cacheWasUsed = false; try { user = this.retrieveUser(username, (UsernamePasswordAuthenticationToken)authentication); } catch (UsernameNotFoundException var6) { this.logger.debug("User '" + username + "' not found"); //因為hideUserNotFoundExceptions屬性默認為true,所以無論是拋出UsernameNotFoundException,還是BadCredentialsException //都統一拋出的是密碼錯誤異常這個類BadCredentialsException。 if (this.hideUserNotFoundExceptions) { throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials")); } throw var6; ... } ``` <br/> **3. 解決辦法** 認證邏輯接口 UserDetailsService 拋出異常改為 BadCredentialsException,或 InternalAuthenticationServiceException 即可。 ```java public class LoginServiceImpl implements UserDetailsService { @Autowired private AccountService accountService; @Override public UserDetails loadUserByUsername(String username) throws BadCredentialsException{ Account account = accountService.findByUsername(username); if (account == null) { throw new BadCredentialsException("用戶不存在!"); } List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("admin"); return new User(username, account.getPassword(), authorities); } } ----------------------------------------------------------------------------------------- public class LoginServiceImpl implements UserDetailsService { @Autowired private AccountService accountService; @Override public UserDetails loadUserByUsername(String username) throws InternalAuthenticationServiceException{ Account account = accountService.findByUsername(username); if (account == null) { throw new InternalAuthenticationServiceException("用戶不存在!"); } List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("admin"); return new User(username, account.getPassword(), authorities); } } ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看