<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        SpringBoot和SpringSecurity處理Ajax登錄請求的問題

        來源:懂視網 責編:小采 時間:2020-11-27 19:35:09
        文檔

        SpringBoot和SpringSecurity處理Ajax登錄請求的問題

        SpringBoot和SpringSecurity處理Ajax登錄請求的問題:這篇文章主要介紹了SpringBoot+SpringSecurity處理Ajax登錄請求問題,本文給大家介紹的非常不錯,具有參考借鑒價值,需要的朋友可以參考下最近在項目中遇到了這樣一個問題:前后端分離,前端用Vue來做,所有的數據請求都使用vue-resource,沒有使
        推薦度:
        導讀SpringBoot和SpringSecurity處理Ajax登錄請求的問題:這篇文章主要介紹了SpringBoot+SpringSecurity處理Ajax登錄請求問題,本文給大家介紹的非常不錯,具有參考借鑒價值,需要的朋友可以參考下最近在項目中遇到了這樣一個問題:前后端分離,前端用Vue來做,所有的數據請求都使用vue-resource,沒有使
        這篇文章主要介紹了SpringBoot+SpringSecurity處理Ajax登錄請求問題,本文給大家介紹的非常不錯,具有參考借鑒價值,需要的朋友可以參考下

        最近在項目中遇到了這樣一個問題:前后端分離,前端用Vue來做,所有的數據請求都使用vue-resource,沒有使用表單,因此數據交互都是使用JSON,后臺使用Spring Boot,權限驗證使用了Spring Security,因為之前用Spring Security都是處理頁面的,這次單純處理Ajax請求,因此記錄下遇到的一些問題。這里的解決方案不僅適用于Ajax請求,也可以解決移動端請求驗證。

        創建工程

        首先我們需要創建一個Spring Boot工程,創建時需要引入Web、Spring Security、MySQL和MyBatis(數據庫框架其實隨意,我這里使用MyBatis),創建好之后,依賴文件如下:

        <dependency>
         <groupId>org.mybatis.spring.boot</groupId>
         <artifactId>mybatis-spring-boot-starter</artifactId>
         <version>1.3.1</version>
        </dependency>
        <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
         <scope>runtime</scope>
        </dependency>
        <dependency>
         <groupId>commons-codec</groupId>
         <artifactId>commons-codec</artifactId>
         <version>1.11</version>
        </dependency>

        注意最后一個 commons-codec 依賴是我手動加入進來的,這是一個Apache的開源項目,可以用來生成MD5消息摘要,我在后文中將對密碼進行簡單的處理。

        創建數據庫并配置

        為了簡化邏輯,我這里創建了三個表,分別是用戶表、角色表、用戶角色關聯表,如下:

        接下來我們需要在application.properties中對自己的數據庫進行簡單的配置,這里各位小伙伴視自己的具體情況而定。

        spring.datasource.url=jdbc:mysql:///vueblog
        spring.datasource.username=root
        spring.datasource.password=123

        構造實體類

        這里主要是指構造用戶類,這里的用戶類比較特殊,必須實現UserDetails接口,如下:

        public class User implements UserDetails {
         private Long id;
         private String username;
         private String password;
         private String nickname;
         private boolean enabled;
         private List<Role> roles;
         @Override
         public boolean isAccountNonExpired() {
         return true;
         }
         @Override
         public boolean isAccountNonLocked() {
         return true;
         }
         @Override
         public boolean isCredentialsNonExpired() {
         return true;
         }
         @Override
         public boolean isEnabled() {
         return enabled;
         }
         @Override
         public List<GrantedAuthority> getAuthorities() {
         List<GrantedAuthority> authorities = new ArrayList<>();
         for (Role role : roles) {
         authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));
         }
         return authorities;
         }
         //getter/setter省略...
        }

        實現了UserDetails接口之后,該接口中有幾個方法需要我們實現,四個返回Boolean的方法都是見名知意,enabled表示檔期賬戶是否啟用,這個我數據庫中確實有該字段,因此根據查詢結果返回,其他的為了簡單期間都直接返回true,getAuthorities方法返回當前用戶的角色信息,用戶的角色其實就是roles中的數據,將roles中的數據轉換為List<GrantedAuthority>之后返回即可, 這里有一個要注意的地方,由于我在數據庫中存儲的角色名都是諸如‘超級管理員'、‘普通用戶'之類的,并不是以 ROLE_ 這樣的字符開始的,因此需要在這里手動加上 ROLE_ ,切記 。

        另外還有一個Role實體類,比較簡單,按照數據庫的字段創建即可,這里不再贅述。

        創建UserService

        這里的UserService也比較特殊,需要實現UserDetailsService接口,如下:

        @Service
        public class UserService implements UserDetailsService {
         @Autowired
         UserMapper userMapper;
         @Autowired
         RolesMapper rolesMapper;
         @Override
         public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
         User user = userMapper.loadUserByUsername(s);
         if (user == null) {
         //避免返回null,這里返回一個不含有任何值的User對象,在后期的密碼比對過程中一樣會驗證失敗
         return new User();
         }
         //查詢用戶的角色信息,并返回存入user中
         List<Role> roles = rolesMapper.getRolesByUid(user.getId());
         user.setRoles(roles);
         return user;
         }
        }

        實現了UserDetailsService接口之后,我們需要實現該接口中的loadUserByUsername方法,即根據用戶名查詢用戶。這里注入了兩個MyBatis中的Mapper,UserMapper用來查詢用戶,RolesMapper用來查詢角色。在loadUserByUsername方法中,首先根據傳入的參數(參數就是用戶登錄時輸入的用戶名)去查詢用戶,如果查到的用戶為null,可以直接拋一個UsernameNotFoundException異常,但是我為了處理方便,返回了一個沒有任何值的User對象,這樣在后面的密碼比對過程中一樣會發現登錄失敗的(這里大家根據自己的業務需求調整即可),如果查到的用戶不為null,此時我們根據查到的用戶id再去查詢該用戶的角色,并將查詢結果放入到user對象中,這個查詢結果將在user對象的getAuthorities方法中用上。

        Security配置

        我們先來看一下我的Security配置,然后我再來一一解釋:

        @Configuration
        public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
         @Autowired
         UserService userService;
         @Override
         protected void configure(AuthenticationManagerBuilder auth) throws Exception {
         auth.userDetailsService(userService).passwordEncoder(new PasswordEncoder() {
         @Override
         public String encode(CharSequence charSequence) {
         return DigestUtils.md5DigestAsHex(charSequence.toString().getBytes());
         }
         /**
         * @param charSequence 明文
         * @param s 密文
         * @return
         */
         @Override
         public boolean matches(CharSequence charSequence, String s) {
         return s.equals(DigestUtils.md5DigestAsHex(charSequence.toString().getBytes()));
         }
         });
         }
         @Override
         protected void configure(HttpSecurity http) throws Exception {
         http.authorizeRequests()
         .antMatchers("/admin/**").hasRole("超級管理員")
         .anyRequest().authenticated()//其他的路徑都是登錄后即可訪問
         .and().formLogin().loginPage("/login_page").successHandler(new AuthenticationSuccessHandler() {
         @Override
         public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
         httpServletResponse.setContentType("application/json;charset=utf-8");
         PrintWriter out = httpServletResponse.getWriter();
         out.write("{\"status\":\"ok\",\"msg\":\"登錄成功\"}");
         out.flush();
         out.close();
         }
         })
         .failureHandler(new AuthenticationFailureHandler() {
         @Override
         public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
         httpServletResponse.setContentType("application/json;charset=utf-8");
         PrintWriter out = httpServletResponse.getWriter();
         out.write("{\"status\":\"error\",\"msg\":\"登錄失敗\"}");
         out.flush();
         out.close();
         }
         }).loginProcessingUrl("/login")
         .usernameParameter("username").passwordParameter("password").permitAll()
         .and().logout().permitAll().and().csrf().disable();
         }
         @Override
         public void configure(WebSecurity web) throws Exception {
         web.ignoring().antMatchers("/reg");
         }
        }

        這是我們配置的核心,小伙伴們聽我一一道來:

        1.首先這是一個配置類,因此記得加上@Configuration注解,又因為這是Spring Security的配置,因此記得繼承WebSecurityConfigurerAdapter。

        2.將剛剛創建好的UserService注入進來,一會我們要用。

        3.configure(AuthenticationManagerBuilder auth)方法中用來配置我們的認證方式,在auth.userDetailsService()方法中傳入userService,這樣userService中的loadUserByUsername方法在用戶登錄時將會被自動調用。后面的passwordEncoder是可選項,可寫可不寫,因為我是將用戶的明文密碼生成了MD5消息摘要后存入數據庫的,因此在登錄時也需要對明文密碼進行處理,所以就加上了passwordEncoder,加上passwordEncoder后,直接new一個PasswordEncoder匿名內部類即可,這里有兩個方法要實現,看名字就知道方法的含義,第一個方法encode顯然是對明文進行加密,這里我使用了MD5消息摘要,具體的實現方法是由commons-codec依賴提供的;第二個方法matches是密碼的比對,兩個參數,第一個參數是明文密碼,第二個是密文,這里只需要對明文加密后和密文比較即可(小伙伴如果對此感興趣可以繼續考慮密碼加鹽)。

        4.configure(HttpSecurity http)用來配置我們的認證規則等,authorizeRequests方法表示開啟了認證規則配置,antMatchers("/admin/**").hasRole("超級管理員")表示 /admin/** 的路徑需要有‘超級管理員'角色的用戶才能訪問,我在網上看到小伙伴對hasRole方法中要不要加 ROLE_ 前綴有疑問,這里是不要加的,如果用hasAuthority方法才需要加。anyRequest().authenticated()表示其他所有路徑都是需要認證/登錄后才能訪問。接下來我們配置了登錄頁面為login_page,登錄處理路徑為/login,登錄用戶名為username,密碼為password,并配置了這些路徑都可以直接訪問,注銷登陸也可以直接訪問,最后關閉csrf。在successHandler中,使用response返回登錄成功的json即可,切記不可以使用defaultSuccessUrl,defaultSuccessUrl是只登錄成功后重定向的頁面,使用failureHandler也是由于相同的原因。

        5.configure(WebSecurity web)方法中我配置了一些過濾規則,不贅述。

        6.另外,對于靜態文件,如 /images/**/css/**/js/** 這些路徑,這里默認都是不攔截的。

        Controller

        最后來看看我們的Controller,如下:

        @RestController
        public class LoginRegController {
        
         /**
         * 如果自動跳轉到這個頁面,說明用戶未登錄,返回相應的提示即可
         * <p>
         * 如果要支持表單登錄,可以在這個方法中判斷請求的類型,進而決定返回JSON還是HTML頁面
         *
         * @return
         */
         @RequestMapping("/login_page")
         public RespBean loginPage() {
         return new RespBean("error", "尚未登錄,請登錄!");
         }
        }

        這個Controller整體來說還是比較簡單的,RespBean一個響應bean,返回一段簡單的json,不贅述,這里需要小伙伴注意的是 login_page ,我們配置的登錄頁面是一個 login_page ,但實際上 login_page 并不是一個頁面,而是返回一段JSON,這是因為當我未登錄就去訪問其他頁面時Spring Security會自動跳轉到到 login_page 頁面,但是在Ajax請求中,不需要這種跳轉,我要的只是是否登錄的提示,所以這里返回json即可。

        測試

        最后小伙伴可以使用POSTMAN或者RESTClient等工具來測試登錄和權限問題,我就不演示了。

        Ok,經過上文的介紹,想必小伙伴們對Spring Boot+Spring Security處理Ajax登錄請求已經有所了解了,好了,本文就說到這里,有問題歡迎留言討論

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        SpringBoot和SpringSecurity處理Ajax登錄請求的問題

        SpringBoot和SpringSecurity處理Ajax登錄請求的問題:這篇文章主要介紹了SpringBoot+SpringSecurity處理Ajax登錄請求問題,本文給大家介紹的非常不錯,具有參考借鑒價值,需要的朋友可以參考下最近在項目中遇到了這樣一個問題:前后端分離,前端用Vue來做,所有的數據請求都使用vue-resource,沒有使
        推薦度:
        標簽: 請求 問題 sp
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 国产免费av一区二区三区| 搡女人免费免费视频观看| 日韩免费a级毛片无码a∨| 亚洲美女视频网站| 在线a免费观看最新网站| 亚洲成a人片7777| 成人免费大片免费观看网站| 亚洲码一区二区三区| **aaaaa毛片免费| 久久久久se色偷偷亚洲精品av| 国产免费AV片在线播放唯爱网| 久久亚洲精品国产亚洲老地址| 在线免费观看一级片| 亚洲国产精品无码第一区二区三区| 美女黄网站人色视频免费国产| 日韩色日韩视频亚洲网站| 亚洲精品国自产拍在线观看| 久久免费国产精品| 亚洲最新视频在线观看| 黄瓜视频高清在线看免费下载 | 亚洲电影一区二区三区| 99国产精品视频免费观看| 亚洲一区电影在线观看| 国产成人在线观看免费网站| jyzzjyzz国产免费观看| 亚洲av无码一区二区三区网站| 国产成人精品免费午夜app | 一级毛片免费播放试看60分钟| 亚洲人成网站在线播放vr| 1000部无遮挡拍拍拍免费视频观看 | 成人午夜免费福利视频| 丰满亚洲大尺度无码无码专线| 久久国产成人精品国产成人亚洲| 免费观看91视频| 亚洲熟妇无码AV| 亚洲人成人无码网www电影首页 | WWW国产亚洲精品久久麻豆| 综合亚洲伊人午夜网| 99re热免费精品视频观看| 一级特黄录像视频免费| 亚洲狠狠ady亚洲精品大秀|