SpringSecurity 快速實(shí)現(xiàn)項(xiàng)目

我的開(kāi)發(fā)環(huán)境是springboot(下面簡(jiǎn)稱(chēng)sb)+freemarker+maven

如大家所知道的,sb里面沒(méi)有配置文件嚎京,需要通過(guò)類(lèi)加載或者解析xml來(lái)配置一些東西,這也是初學(xué)sb的一個(gè)頭痛點(diǎn)。(我當(dāng)時(shí)就是准脂,哈哈)

好的不多嗶嗶,直入正題檬洞。但是我還是想告誡一些沒(méi)有sb讀配置文件的經(jīng)驗(yàn)的小司機(jī)狸膏。可能會(huì)不好理解添怔,但是不要放棄湾戳,一步一步跟著我來(lái),就可以

1. pom依賴(lài)

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

第一個(gè)依賴(lài)是security的核心依賴(lài)包广料,第二個(gè)是security對(duì)freemarker的標(biāo)簽的支持包砾脑。
加了這兩個(gè)東西之后,重啟項(xiàng)目艾杏,它就會(huì)彈出讓你登錄的窗口韧衣。



你可能會(huì)迷惑,我什么都沒(méi)配置购桑,為什么就給我要密碼畅铭?因?yàn)閟ecurity依賴(lài)包只要引入了,它會(huì)默認(rèn)給項(xiàng)目加入密碼勃蜘。用戶(hù)名是user 默認(rèn)密碼在控制臺(tái)找下硕噩。


實(shí)際開(kāi)發(fā)中,我們肯定不是這樣讓用戶(hù)認(rèn)證缭贡。所以我們要重寫(xiě)security的實(shí)現(xiàn)類(lèi)炉擅。

2. 繼承重寫(xiě)WebSecurityConfigurerAdapter類(lèi)

/**
 *
 * Created by Fant.J.
 * 2017/10/26 18:48
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{

    //返回 BCrypt  加密對(duì)象
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
//    @Autowired
//    private AuthenticationSuccessHandler myAuthenticationSuccessHandler;
//    @Autowired
//    private MyAuthenticationFailHandler myAuthenticationFailHandler;


    @Bean
    protected UserDetailsService userDetailServiceImpl(){
        return new UserDetailServiceImpl();
    }
    @Override
    protected void configure(HttpSecurity http)throws Exception{
//        ValidateCodeFilter filter = new ValidateCodeFilter();
//        //寫(xiě)入自定義錯(cuò)誤過(guò)濾器
//        filter.setAuthenticationFailureHandler(myAuthenticationFailHandler);
        //表單登錄
       http.formLogin()         
 //        http.httpBasic()
                .and()
                .authorizeRequests()
                .anyRequest()
                .authenticated();

        http
                .headers()
                .frameOptions()
                .sameOrigin();


    }
}

http.formLogin() 表示以表單的形式登錄,authorizeRequests()表示什么請(qǐng)求需要驗(yàn)證呢阳惹?anyRequest()嗯坑资,所有的請(qǐng)求都需要驗(yàn)證。authenticated();證明是有效的情況下穆端。
自己整段話連起來(lái)袱贮,大家就懂了這種寫(xiě)法的含義了。
相信一些有心人在上面的類(lèi)中看到了這段代碼

    @Bean
    protected UserDetailsService userDetailServiceImpl(){
        return new UserDetailServiceImpl();
    }

我們來(lái)看下這個(gè)UserDetailsService這個(gè)官方接口
image.png

根據(jù)方法名我們能看出來(lái),它是用來(lái)通過(guò)username加載User信息的攒巍,這和form驗(yàn)證就關(guān)系上了嗽仪。你只需要把這個(gè)類(lèi)注入到類(lèi)里,它會(huì)自動(dòng)去找這個(gè)實(shí)現(xiàn)類(lèi)柒莉,那么下面我們來(lái)看下我寫(xiě)的這個(gè)實(shí)現(xiàn)類(lèi)闻坚。

3. UserDetailServiceImpl 實(shí)現(xiàn)UserDetailsService接口


/**
 * Created by Fant.J.
 * 2017/10/26 20:54
 */
@Component
@Slf4j
public class UserDetailServiceImpl implements UserDetailsService{
    @Autowired
    UserAdminMapper userAdminMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    /** 超級(jí)用戶(hù) */
    private static final Integer USER_POWER_ADMIN = 1;
    /** 普通用戶(hù) */
    private static final Integer USER_POWER_USER = 2;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        try {
            UserAdmin userAdmin = userAdminMapper.selectByUsername(username);
            log.info("登錄用戶(hù)名" + username);
            log.info("數(shù)據(jù)庫(kù)密碼" + userAdmin.getPassword());
            if (userAdmin == null) {
                throw new UsernameNotFoundException("沒(méi)有找到");
            }
            //獲取用戶(hù)使用狀態(tài)
            boolean status = false;
            if (userAdmin.getUserStatus() == 1){
                status = true;
            }
            if (userAdmin.getUserPower() == 1) {
                log.info("ADMIN用戶(hù)"+userAdmin.getUserAdminName()+"登錄");
                return new User(username, passwordEncoder.encode(userAdmin.getPassword()),
                        status, true, true, true,
                        AuthorityUtils.commaSeparatedStringToAuthorityList("ADMIN"));
            } else if (userAdmin.getUserPower() == 2) {
                log.info("ADMIN用戶(hù)"+userAdmin.getUserAdminName()+"登錄");
                return new User(username, passwordEncoder.encode(userAdmin.getPassword()),
                        true, true, true, true,
                        AuthorityUtils.commaSeparatedStringToAuthorityList("USER"));
            } else {
                log.error("用戶(hù)權(quán)限錯(cuò)誤異常,默認(rèn)為USER普通用戶(hù)");
                return new User(username, passwordEncoder.encode(userAdmin.getPassword()),
                        true, true, true, true,
                        AuthorityUtils.commaSeparatedStringToAuthorityList("USER"));
            }
        }catch (Exception e){
            log.error("用戶(hù)權(quán)限錯(cuò)誤異常"+e.getMessage());
            throw new MyException("用戶(hù)權(quán)限錯(cuò)誤異常");
        }
    }
}

返回類(lèi)型必須是UserDetails(官方提供類(lèi)),來(lái)看下它的源碼

image.png

可以看到里面包含了賬號(hào)密碼,和是否過(guò)期兢孝,是否可用窿凤,是否被鎖,是否有效四個(gè)狀態(tài)跨蟹。所以我代碼里有
return new User(username, passwordEncoder.encode(userAdmin.getPassword()), status, true, true, true, AuthorityUtils.commaSeparatedStringToAuthorityList("ADMIN"));
大家就能看懂了雳殊,AuthorityUtils.commaSeparatedStringToAuthorityList("ADMIN"));這個(gè)是自定義添加的用戶(hù)身份,再開(kāi)發(fā)過(guò)程中可把它封裝起來(lái)窗轩。(我在這里由于數(shù)據(jù)庫(kù)設(shè)計(jì)原因定成死的)夯秃,說(shuō)明它是個(gè)admin身份。passwordEncoder.encode是security提供的加密痢艺,(挺高端的仓洼,隨機(jī)生成鹽然后插入到密碼里。每次登錄都不一樣堤舒,還提供了passwordEncoder.match()方法色建,兩者聯(lián)合判斷用戶(hù)是否有效),不多說(shuō) 看源碼
image.png

然后你返回去看我的SecurityConfig類(lèi)舌缤,你會(huì)找到

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

這個(gè)注入類(lèi)就是獲取impl中從數(shù)據(jù)庫(kù)里查出來(lái)的密碼镀岛,然后match判斷。所以就要求我們注冊(cè)用戶(hù)的時(shí)候友驮,先encode()一下再存入數(shù)據(jù)庫(kù)漂羊,然后讀出來(lái)直接返回,我的這個(gè)impl是從數(shù)據(jù)庫(kù)里讀出密碼然后加密的卸留,因?yàn)槲遗聰?shù)據(jù)庫(kù)密碼我都會(huì)忘記走越。。
按照需求來(lái)吧耻瑟。

4. 啟動(dòng)項(xiàng)目

image.png

security默認(rèn)有個(gè)form表單提交頁(yè)面旨指。我們輸入錯(cuò)誤的密碼。
image.png

輸入錯(cuò)誤的賬號(hào)
image.png

看上去沒(méi)有提示喳整,因?yàn)槲覀儧](méi)有捕獲這個(gè)異常谆构。
我們輸入正確的帳號(hào)密碼
image.png

進(jìn)來(lái)了。但是測(cè)試的時(shí)候你會(huì)發(fā)現(xiàn)個(gè)問(wèn)題框都。表單提交的時(shí)候會(huì)報(bào)403無(wú)權(quán)限訪問(wèn)異常
搬素。好好想想我們引入了兩個(gè)依賴(lài)包,第二個(gè)還沒(méi)用呢!
在每個(gè)有form提交的地方都加上
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
這是security框架token認(rèn)證需要的東西熬尺。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末摸屠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子粱哼,更是在濱河造成了極大的恐慌季二,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件揭措,死亡現(xiàn)場(chǎng)離奇詭異胯舷,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)绊含,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)桑嘶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人艺挪,你說(shuō)我怎么就攤上這事不翩”铮” “怎么了麻裳?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)器钟。 經(jīng)常有香客問(wèn)我津坑,道長(zhǎng),這世上最難降的妖魔是什么傲霸? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任疆瑰,我火速辦了婚禮,結(jié)果婚禮上昙啄,老公的妹妹穿的比我還像新娘穆役。我一直安慰自己,他們只是感情好梳凛,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布耿币。 她就那樣靜靜地躺著,像睡著了一般韧拒。 火紅的嫁衣襯著肌膚如雪淹接。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,785評(píng)論 1 290
  • 那天叛溢,我揣著相機(jī)與錄音塑悼,去河邊找鬼。 笑死楷掉,一個(gè)胖子當(dāng)著我的面吹牛厢蒜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼郭怪,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼支示!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起鄙才,我...
    開(kāi)封第一講書(shū)人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤颂鸿,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后攒庵,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體嘴纺,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年浓冒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了栽渴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡稳懒,死狀恐怖闲擦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情场梆,我是刑警寧澤墅冷,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站或油,受9級(jí)特大地震影響寞忿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜顶岸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一腔彰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧辖佣,春花似錦霹抛、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至雏搂,卻和暖如春藕施,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背凸郑。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工裳食, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人芙沥。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓诲祸,卻偏偏與公主長(zhǎng)得像浊吏,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子救氯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容