SpringSecurity在前后端分離項目中的實現(xiàn)

一晒屎、基本思路

服務端通過 JSON字符串喘蟆,告訴前端用戶是否登錄、認證鼓鲁;前端根據(jù)這些提示跳轉對應的登錄頁履肃、認證頁

二、具體實現(xiàn)

AuthenticationEntryPoint:未登錄

public class AjaxAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
       
        AjaxResponseBody responseBody = new AjaxResponseBody();

        responseBody.setStatus("000");
        
        responseBody.setMsg("無訪問權限坐桩,請先登錄");

        httpServletResponse.getWriter().write(JSON.toJSONString(responseBody));
    }
}

AuthenticationFailureHandler:登錄失敗

public class AjaxAuthenticationFailureHandler implements AuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        
        AjaxResponseBody responseBody = new AjaxResponseBody();

        responseBody.setStatus("400");
       
        responseBody.setMsg("登錄失敗");

        httpServletResponse.getWriter().write(JSON.toJSONString(responseBody));
    }
}

AuthenticationSuccessHandler :登錄成功

public class AjaxAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        
        AjaxResponseBody responseBody = new AjaxResponseBody();

        responseBody.setStatus("200");
       
        responseBody.setMsg("登錄成功");

        httpServletResponse.getWriter().write(JSON.toJSONString(responseBody));
    }
}

AccessDeniedHandler:無權訪問

public class AjaxAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
        
        AjaxResponseBody responseBody = new AjaxResponseBody();

        responseBody.setStatus("300");
       
        responseBody.setMsg("無權訪問");

        httpServletResponse.getWriter().write(JSON.toJSONString(responseBody));
    }
}

LogoutSuccessHandler:注銷

public class AjaxLogoutSuccessHandler implements LogoutSuccessHandler {
    @Override
    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        
        AjaxResponseBody responseBody = new AjaxResponseBody();

        responseBody.setStatus("100");
        
        responseBody.setMsg("注銷成功");

        httpServletResponse.getWriter().write(JSON.toJSONString(responseBody));
    }
}

UserDetails:定義User對象

public class SelfUserDetails implements UserDetails, Serializable {
    private String username;
    private String password;
    private Set<? extends GrantedAuthority> authorities;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return this.authorities;
    }

    public void setAuthorities(Set<? extends GrantedAuthority> authorities) {
        this.authorities = authorities;
    }

    @Override
    public String getPassword() { 
        return this.password;
    }

    @Override
    public String getUsername() {
        return this.username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }
}

UserDetailsService:用戶權限認證

public class SelfUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        SelfUserDetails userInfo = new SelfUserDetails();
        userInfo.setUsername(username);
        Md5PasswordEncoder md5PasswordEncoder = new Md5PasswordEncoder();
        String encodePassword = md5PasswordEncoder.encodePassword("123", username); 
        userInfo.setPassword(encodePassword);
        Set authoritiesSet = new HashSet();
        GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_ADMIN"); 
        authoritiesSet.add(authority);
        userInfo.setAuthorities(authoritiesSet);
        return userInfo;
    }
}

AuthenticationProvider:前端交互

public class SelfAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    SelfUserDetailsService userDetailsService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String userName = (String) authentication.getPrincipal();
        String password = (String) authentication.getCredentials(); 

        Md5PasswordEncoder md5PasswordEncoder = new Md5PasswordEncoder();
        String encodePwd = md5PasswordEncoder.encodePassword(password, userName);

        UserDetails userInfo = userDetailsService.loadUserByUsername(userName);

        if (!userInfo.getPassword().equals(encodePwd)) {
            throw new BadCredentialsException("用戶名密碼不正確,請重新登陸封锉!");
        }

        return new UsernamePasswordAuthenticationToken(userName, password, userInfo.getAuthorities());
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return true;
    }
}

WebSecurityConfigurerAdapter:登錄攔截全局配置

public class SpringSecurityConf extends WebSecurityConfigurerAdapter {

    @Autowired
    AjaxAuthenticationEntryPoint authenticationEntryPoint;  //  未登陸時返回 JSON 格式的數(shù)據(jù)給前端(否則為 html)

    @Autowired
    AjaxAuthenticationSuccessHandler authenticationSuccessHandler;  // 登錄成功返回的 JSON 格式數(shù)據(jù)給前端(否則為 html)

    @Autowired
    AjaxAuthenticationFailureHandler authenticationFailureHandler;  //  登錄失敗返回的 JSON 格式數(shù)據(jù)給前端(否則為 html)

    @Autowired
    AjaxLogoutSuccessHandler  logoutSuccessHandler;  // 注銷成功返回的 JSON 格式數(shù)據(jù)給前端(否則為 登錄時的 html)

    @Autowired
    AjaxAccessDeniedHandler accessDeniedHandler;    // 無權訪問返回的 JSON 格式數(shù)據(jù)給前端(否則為 403 html 頁面)

    @Autowired
    SelfAuthenticationProvider provider; // 自定義安全認證

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 加入自定義的安全認證
        auth.authenticationProvider(provider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable()

                .httpBasic().authenticationEntryPoint(authenticationEntryPoint)

                .and()
                .authorizeRequests()

                .anyRequest()
                .authenticated()// 其他 url 需要身份認證

                .and()
                .formLogin()  //開啟登錄
                .successHandler(authenticationSuccessHandler) // 登錄成功
                .failureHandler(authenticationFailureHandler) // 登錄失敗
                .permitAll()

                .and()
                .logout()
                .logoutSuccessHandler(logoutSuccessHandler)
                .permitAll();

        http.exceptionHandling().accessDeniedHandler(accessDeniedHandler); // 無權訪問 JSON 格式的數(shù)據(jù)

    }
}
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末绵跷,一起剝皮案震驚了整個濱河市膘螟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碾局,老刑警劉巖荆残,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異净当,居然都是意外死亡内斯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門像啼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來俘闯,“玉大人,你說我怎么就攤上這事忽冻≌胬剩” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵僧诚,是天一觀的道長遮婶。 經(jīng)常有香客問我,道長湖笨,這世上最難降的妖魔是什么旗扑? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮慈省,結果婚禮上臀防,老公的妹妹穿的比我還像新娘。我一直安慰自己辫呻,他們只是感情好清钥,可當我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著放闺,像睡著了一般祟昭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上怖侦,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天篡悟,我揣著相機與錄音,去河邊找鬼匾寝。 笑死搬葬,一個胖子當著我的面吹牛,可吹牛的內容都是我干的艳悔。 我是一名探鬼主播急凰,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼猜年!你這毒婦竟也來了抡锈?” 一聲冷哼從身側響起疾忍,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎床三,沒想到半個月后一罩,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡撇簿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年聂渊,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片四瘫。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡汉嗽,死狀恐怖,靈堂內的尸體忽然破棺而出莲组,到底是詐尸還是另有隱情诊胞,我是刑警寧澤,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布锹杈,位于F島的核電站撵孤,受9級特大地震影響,放射性物質發(fā)生泄漏竭望。R本人自食惡果不足惜邪码,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望咬清。 院中可真熱鬧闭专,春花似錦、人聲如沸旧烧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掘剪。三九已至平委,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間夺谁,已是汗流浹背廉赔。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留匾鸥,地道東北人蜡塌。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像勿负,于是被迫代替她去往敵國和親馏艾。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內容