Java SpringSecurity+JWT實(shí)現(xiàn)登錄認(rèn)證
前言:
學(xué)習(xí)過我的mall項(xiàng)目的應(yīng)該知道,mall-admin
模塊是使用SpringSecurity+JWT來實(shí)現(xiàn)登錄認(rèn)證的,而mall-portal
模塊是使用的SpringSecurity基于Session的默認(rèn)機(jī)制來實(shí)現(xiàn)登陸認(rèn)證的。很多小伙伴都找不到mall-portal
的登錄接口,最近我把這兩個(gè)模塊的登錄認(rèn)證給統(tǒng)一了,都使用SpringSecurity+JWT的形式實(shí)現(xiàn)。主要是通過把登錄認(rèn)證的通用邏輯抽取到了mall-security
模塊來實(shí)現(xiàn)的,下面我們講講如何使用mall-security
模塊來實(shí)現(xiàn)登錄認(rèn)證,僅需四步即可。
整合步驟
這里我們以
mall-portal
改造為例來說說如何實(shí)現(xiàn)。
第一步,給需要登錄認(rèn)證的模塊添加mall-security
依賴:
<dependency> <groupId>com.macro.mall</groupId> <artifactId>mall-security</artifactId> </dependency>
第二步,添加MallSecurityConfig配置類,繼承mall-security
中的SecurityConfig配置,并且配置一個(gè)UserDetailsService接口的實(shí)現(xiàn)類,用于獲取登錄用戶詳情:
/** * mall-security模塊相關(guān)配置 * Created by macro on 2019/11/5. */ @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled=true) publicclass MallSecurityConfig extends SecurityConfig { @Autowired private UmsMemberService memberService; @Bean public UserDetailsService userDetailsService() { //獲取登錄用戶信息 return username -> memberService.loadUserByUsername(username); } }
第三步,在application.yml中配置下不需要安全保護(hù)的資源路徑:
secure: ignored: urls:#安全路徑白名單 -/swagger-ui.html -/swagger-resources/** -/swagger/** -/**/v2/api-docs -/**/*.js -/**/*.css -/**/*.png -/**/*.ico -/webjars/springfox-swagger-ui/** -/druid/** -/actuator/** -/sso/** -/home/**
第四步,在UmsMemberController中實(shí)現(xiàn)登錄和刷新token的接口:
/** * 會(huì)員登錄注冊(cè)管理Controller * Created by macro on 2018/8/3. */ @Controller @Api(tags = "UmsMemberController", description = "會(huì)員登錄注冊(cè)管理") @RequestMapping("/sso") publicclass UmsMemberController { @Value("${jwt.tokenHeader}") private String tokenHeader; @Value("${jwt.tokenHead}") private String tokenHead; @Autowired private UmsMemberService memberService; @ApiOperation("會(huì)員登錄") @RequestMapping(value = "/login", method = RequestMethod.POST) @ResponseBody public CommonResult login(@RequestParam String username, @RequestParam String password) { String token = memberService.login(username, password); if (token == null) { return CommonResult.validateFailed("用戶名或密碼錯(cuò)誤"); } Map<String, String> tokenMap = new HashMap<>(); tokenMap.put("token", token); tokenMap.put("tokenHead", tokenHead); return CommonResult.success(tokenMap); } @ApiOperation(value = "刷新token") @RequestMapping(value = "/refreshToken", method = RequestMethod.GET) @ResponseBody public CommonResult refreshToken(HttpServletRequest request) { String token = request.getHeader(tokenHeader); String refreshToken = memberService.refreshToken(token); if (refreshToken == null) { return CommonResult.failed("token已經(jīng)過期!"); } Map<String, String> tokenMap = new HashMap<>(); tokenMap.put("token", refreshToken); tokenMap.put("tokenHead", tokenHead); return CommonResult.success(tokenMap); } }
實(shí)現(xiàn)原理
將SpringSecurity+JWT的代碼封裝成通用模塊后,就可以方便其他需要登錄認(rèn)證的模塊來使用,下面我們來看看它是如何實(shí)現(xiàn)的,首先我們看下
mall-security
的目錄結(jié)構(gòu)。
目錄結(jié)構(gòu)
mall-security ├── component | ├── JwtAuthenticationTokenFilter -- JWT登錄授權(quán)過濾器 | ├── RestAuthenticationEntryPoint -- 自定義返回結(jié)果:未登錄或登錄過期 | └── RestfulAccessDeniedHandler -- 自定義返回結(jié)果:沒有權(quán)限訪問時(shí) ├── config | ├── IgnoreUrlsConfig -- 用于配置不需要安全保護(hù)的資源路徑 | └── SecurityConfig -- SpringSecurity通用配置 └── util └── JwtTokenUtil -- JWT的token處理工具類
做了哪些變化
其實(shí)我也就添加了兩個(gè)類,一個(gè)IgnoreUrlsConfig,用于從application.yml中獲取不需要安全保護(hù)的資源路徑。一個(gè)SecurityConfig提取了一些SpringSecurity的通用配置。
IgnoreUrlsConfig中的代碼:
/** * 用于配置不需要保護(hù)的資源路徑 * Created by macro on 2018/11/5. */ @Getter @Setter @ConfigurationProperties(prefix = "secure.ignored") publicclass IgnoreUrlsConfig { private List<String> urls = new ArrayList<>(); }
SecurityConfig中的代碼:
/** * 對(duì)SpringSecurity的配置的擴(kuò)展,支持自定義白名單資源路徑和查詢用戶邏輯 * Created by macro on 2019/11/5. */ publicclass SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity httpSecurity) throws Exception { ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = httpSecurity .authorizeRequests(); //不需要保護(hù)的資源路徑允許訪問 for (String url : ignoreUrlsConfig().getUrls()) { registry.antMatchers(url).permitAll(); } //允許跨域請(qǐng)求的OPTIONS請(qǐng)求 registry.antMatchers(HttpMethod.OPTIONS) .permitAll(); // 任何請(qǐng)求需要身份認(rèn)證 registry.and() .authorizeRequests() .anyRequest() .authenticated() // 關(guān)閉跨站請(qǐng)求防護(hù)及不使用session .and() .csrf() .disable() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 自定義權(quán)限拒絕處理類 .and() .exceptionHandling() .accessDeniedHandler(restfulAccessDeniedHandler()) .authenticationEntryPoint(restAuthenticationEntryPoint()) // 自定義權(quán)限攔截器JWT過濾器 .and() .addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService()) .passwordEncoder(passwordEncoder()); } @Bean public PasswordEncoder passwordEncoder() { returnnew BCryptPasswordEncoder(); } @Bean public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter() { returnnew JwtAuthenticationTokenFilter(); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { returnsuper.authenticationManagerBean(); } @Bean public RestfulAccessDeniedHandler restfulAccessDeniedHandler() { returnnew RestfulAccessDeniedHandler(); } @Bean public RestAuthenticationEntryPoint restAuthenticationEntryPoint() { returnnew RestAuthenticationEntryPoint(); } @Bean public IgnoreUrlsConfig ignoreUrlsConfig() { returnnew IgnoreUrlsConfig(); } @Bean public JwtTokenUtil jwtTokenUtil() { returnnew JwtTokenUtil(); } }
到此這篇關(guān)于Java SpringSecurity+JWT實(shí)現(xiàn)登錄認(rèn)證 的文章就介紹到這了,更多相關(guān)Java SpringSecurity 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot項(xiàng)目中出現(xiàn)同名bean異常報(bào)錯(cuò)的解決方法
這篇文章給大家聊聊springboot項(xiàng)目出現(xiàn)同名bean異常報(bào)錯(cuò)如何修復(fù),文中通過代碼示例給大家介紹解決方法非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-01-01MybatisPlusInterceptor依賴變紅如何解決,無(wú)法識(shí)別問題
這篇文章主要介紹了MybatisPlusInterceptor依賴變紅如何解決,無(wú)法識(shí)別問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07一文教會(huì)你使用jmap和MAT進(jìn)行堆內(nèi)存溢出分析
本文介紹關(guān)于jmap和MAT的使用來進(jìn)行堆內(nèi)存溢出分析,因?yàn)檫@個(gè)內(nèi)存溢出是我們手動(dòng)構(gòu)造出來的,查找比較簡(jiǎn)單,真的到了生產(chǎn)上面需要我們仔細(xì)排除2021-09-09Java中的位運(yùn)算符、移位運(yùn)算詳細(xì)介紹
這篇文章主要介紹了Java中的位運(yùn)算符、移位運(yùn)算,有需要的朋友可以參考一下2013-12-12