您好,登錄后才能下訂單哦!
本篇內容介紹了“vue2+springsecurity權限系統怎么實現”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
新建項目,SpringBoot采用2.7.11,spring-boot-starter-security,vue 2.0
默認會自動啟動攔截裝置,可以這樣取消,先這樣配置一下
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
引入依賴
<!-- JWT --> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.2.0</version> </dependency>
邏輯:用戶登錄后,請求頭中加一個token參數,如果有則表示可以訪問,沒有就不能訪問,這是一個小測試還是有點缺陷的
一共有兩個最主要攔截器
登陸驗證攔截器AuthenticationProcessingFilter
資源管理攔截器AbstractSecurityInterceptor
但攔截器里面的實現需要一些組件來實現分別是
AuthenticationManager認證管理器
accessDecisionManager決策管理器等組件來支撐。
流程圖解讀:
用戶提交用戶名、密碼被SecurityFilterChain中的 UsernamePasswordAuthenticationFilter 過濾器獲取到,封裝為請求Authentication,通常情況下是UsernamePasswordAuthenticationToken這個實 現類。
然后過濾器將Authentication提交至認證管理器(AuthenticationManager)進行認證 。
認證成功后, AuthenticationManager 身份管理器返回一個被填充滿了信息的(包括上面提到的權 限信息, 身份信息,細節信息,但密碼通常會被移除) Authentication 實例。
SecurityContextHolder 安全上下文容器將第3步填充了信息的 Authentication
通過 SecurityContextHolder.getContext().setAuthentication(…)方法,設置到其中。 可以看出 AuthenticationManager接口(認證管理器)是認證相關的核心接口,也是發起認證的出發點,它的實 現類為ProviderManager。而Spring Security支持多種認證方式,因此ProviderManager維護著一個 List 列表,存放多種認證方式,最終實際的認證工作是由 AuthenticationProvider完成的。咱們知道 web表單的對應的AuthenticationProvider實現類為 DaoAuthenticationProvider,它的內部又維護著 一個UserDetailsService負責UserDetails的獲取。最終 AuthenticationProvider將UserDetails填充至 Authentication。
現在關掉之前的SecurityAutoConfiguration.class,打開是不是直接跳轉到了登錄頁面呢,無法訪問接口了
先說下創建token的工具類
/** * 簽發JWT * * @param id 用戶ID * @param subject 可以是JSON數據 盡可能少 * @param ttlMillis 不知道 * @return 結果 */ public static String createJWT(String id, String subject, long ttlMillis) { SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; // 獲取當前時間毫秒 long nowMillis = System.currentTimeMillis(); // 獲取當前時間日期類型 Date now = new Date(nowMillis); // 生成一個加密的key SecretKey secretKey = generalKey(); JwtBuilder builder = Jwts.builder() .setId(id) .setSubject(subject) // 主題 .setIssuer("ChiHaiKeJi2016") // 簽發者 .setIssuedAt(now) // 簽發時間 .signWith(signatureAlgorithm, secretKey); // 簽名算法以及密匙 if (ttlMillis >= 0) { long expMillis = nowMillis + ttlMillis; Date expDate = new Date(expMillis); builder.setExpiration(expDate); // 過期時間 } return builder.compact(); } /** * 生成jwt token * @param username 用戶名 */ public static String genJwtToken(String username) { return createJWT(username, username, 60 * 60 * 1000); } /** * 生成加密Key */ public static SecretKey generalKey() { // 目前只知道這個方法生成一個key,并用base64解碼 byte[] encodedKey = Base64.decode(JwtConstant.JWT_SECERT); // 目前不知道啥意思 return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES"); }
配置信息--新建SecurityConfig
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig { // 白名單 private static final String[] URL_WHITE_LIST = {"/login"}; @Resource private LoginHandler loginHandler; // 密碼加密方式 @Bean protected PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { // 開啟跨域 以及csrf攻擊關閉 httpSecurity.cors().and().csrf().disable() // 登錄登出配置 .formLogin() // 登錄成功接口 .successHandler(loginHandler) // 登錄失敗的接口 .failureHandler(loginHandler) // .and().logout().logoutSuccessHandler() // session禁用配置 .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 無狀態,前后端分離 // 攔截規則配置 // // 白名單內容放行 .and().authorizeRequests().antMatchers(URL_WHITE_LIST).permitAll() // 需要認證 .anyRequest().authenticated(); return httpSecurity.build(); } }
配置登錄失敗與成功接口---新建---LoginHandler 處理類
/** * 登錄成功與失敗處理器 */ @Component public class LoginHandler implements AuthenticationSuccessHandler, AuthenticationFailureHandler { // 登錄成功的 @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { response.setContentType("application/json;charset=UTF-8"); ServletOutputStream stream = response.getOutputStream(); // 獲取token String token = JwtUtils.genJwtToken("user"); // 寫入數據 stream.write(JSONUtil.toJsonStr(new Result("登錄成功", token)).getBytes()); stream.flush(); stream.close(); } // 登錄失敗的 @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { response.setContentType("application/json;charset=UTF-8"); ServletOutputStream stream = response.getOutputStream(); String message = exception.getMessage(); if (exception instanceof BadCredentialsException) { message = "用戶名或者密碼錯誤!"; } stream.write(JSONUtil.toJsonStr(new Result(message)).getBytes(StandardCharsets.UTF_8)); stream.flush(); stream.close(); } }
在用戶service實現類中自定義查詢數據庫
@Service public class SysUserServiceImpl implements SysUserService, UserDetailsService { @Resource private SysUserMapper sysUserMapper; // 自定義查詢參數是用戶名 @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>(); sysUserLambdaQueryWrapper.eq(SysUser::getUsername, username); SysUser user = sysUserMapper.selectOne(sysUserLambdaQueryWrapper); if (user == null) { throw new UsernameNotFoundException("用戶名或密碼錯誤!"); } else if ("1".equals(user.getStatus())) { throw new UsernameNotFoundException("該用戶已被封禁!"); } // 第三個是擁有權限 return new User(user.getUsername(), user.getPassword(), getUserAuthority()); } // 權限 private List<GrantedAuthority> getUserAuthority() { return new ArrayList<>(); } }
再來說下前端,先配置跨域
module.exports = { devServer: { host: '0.0.0.0', // 可以忽略不寫 port: 8080, // 它是用來修改你打開后的端口號的 open: true, // 值為 true的話,項目啟動時自動打開到瀏覽器里邊, false不會打開 proxy: { '/api': { target: 'http://localhost:82', // 跨域請求的公共地址 ws: false, // 也可以忽略不寫,不寫不會影響跨域 changeOrigin: true, // 是否開啟跨域,值為 true 就是開啟, false 不開啟 pathRewrite: { '^/api': ''// 注冊全局路徑, 但是在你請求的時候前面需要加上 /api } } } } }
配置axios,因為配置了跨域,這個時候可以直接寫api了
import axios from 'axios' const request = axios.create({ baseURL: '/api' // 因為配置跨域了 }) // 下面這是攔截器,攔截請求,自動加token令牌 request.interceptors.request.use( config => { config.headers.token = `${localStorage.getItem('token')}` return config } ) export default request
說下如何請求前端登錄接口POST請求
登錄接口就是login,傳入username和password就可以了
export const Login = function (data) { return request({ method: 'post', url: 'login', data: qs.stringify(data) }) }
“vue2+springsecurity權限系統怎么實現”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。