springboot簡單集成Security配置的教程
更新時(shí)間:2025年03月31日 09:32:29 作者:愛學(xué)習(xí)的大雄
這篇文章主要介紹了springboot簡單集成Security配置的教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
集成Security安全框架
引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.79</version>
</dependency>編寫配置類WebSecurityConfig(自定義資源權(quán)限規(guī)則處理)
package com.lzj.config;
import com.lzj.config.security.MyUserDetailsService;
import com.lzj.handler.auth.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsUtils;
/**
* <p>
* Security配置類
* </p>
*
* @author:雷子杰
* @date:2022/8/6
*/
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyUserDetailsService myUserDetailsService;
@Autowired
private MyAuthenticationFailureHandler myAuthenticationFailureHandler;
@Autowired
private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
@Autowired
private LogoutSuccessHandlerImpl logoutSuccessHandler;
@Autowired
private MyAuthenticationEntryPoint myAuthenticationEntryPoint;
@Autowired
private MyAccessDeniedHandler myAccessDeniedHandler;
@Override
public void configure(HttpSecurity http) throws Exception {
// 什么是(cors 預(yù)檢請(qǐng)求) 就是你要跨域請(qǐng)求得時(shí)候 你要預(yù)先發(fā)一個(gè)請(qǐng)求看對(duì)面是攔你還是放你
//第1步:解決跨域問題。cors 預(yù)檢請(qǐng)求放行,讓Spring security 放行所有preflight request(cors 預(yù)檢請(qǐng)求)
http.formLogin().loginProcessingUrl("/login").permitAll();
http.authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll();
//放行掉這個(gè)iframe加載
http.headers().frameOptions().disable();
http.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
// //禁用csrf
// http.csrf().disable();
// sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
// .and().headers().cacheControl()
//配置權(quán)限
http.authorizeRequests()
// 放行注冊(cè)請(qǐng)求
.antMatchers(HttpMethod.POST,"/user/registerUser").permitAll()
// 放行swagger
.antMatchers("/swagger-ui.html").permitAll()
.anyRequest()
.access(("@dynamicPermission.checkPermisstion(authentication)"))
.and().csrf().disable();
// 自己的過濾器
http.addFilterAt(myUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
//第6步:處理異常情況:認(rèn)證失敗和權(quán)限不足
http.exceptionHandling().authenticationEntryPoint(myAuthenticationEntryPoint).accessDeniedHandler(myAccessDeniedHandler);
}
//自定義filter交給工廠管理
@Bean
public MyUsernamePasswordAuthenticationFilter myUsernamePasswordAuthenticationFilter() throws Exception {
MyUsernamePasswordAuthenticationFilter filter = new MyUsernamePasswordAuthenticationFilter();
filter.setAuthenticationSuccessHandler(myAuthenticationSuccessHandler);
filter.setAuthenticationFailureHandler(myAuthenticationFailureHandler);
filter.setAuthenticationManager(authenticationManagerBean());
return filter;
}
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
//用戶密碼加密驗(yàn)證
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService( myUserDetailsService).passwordEncoder(passwordEncoder());
}
}編寫配置自定義攔截器(分離式開發(fā))
- MyAuthenticationSuccessHandler(自定義登陸成功處理)
package com.lzj.handler.auth;
import com.alibaba.fastjson.JSON;
import com.lzj.entity.User;
import com.lzj.entity.UserLogin;
import com.lzj.enums.ResultInfo;
import com.lzj.config.security.UserAuth;
import com.lzj.service.UserLoginService;
import com.lzj.utils.IpUtil;
import com.lzj.utils.Result;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
/**
* <p>
* 自定義登陸成功處理
* </p>
*
* @author:雷子杰
* @date:2022/8/6
*/
@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Reference
private UserLoginService userLoginService;
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
//驗(yàn)證成功來到這個(gè)處理器
//然后獲取用戶信息
UserAuth user = (UserAuth) authentication.getPrincipal();
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(JSON.toJSONString(Result.ok()
.setCode(ResultInfo.VERIFY_SUCCESS.getCode())
.setMessage(ResultInfo.VERIFY_SUCCESS.getMessage()).data("user", user)));
//這下面的是非必須的,這是我數(shù)據(jù)庫中用來存儲(chǔ)登陸記錄的一個(gè)表
//更新用戶登錄ip地址,最新登錄時(shí)間
String ipAddress = IpUtil.getIp(request);
String ipSource = IpUtil.getIpSource(ipAddress);
User loginUser = user.getUser();
UserLogin login = new UserLogin();
login.setAvatar(loginUser.getAvatar());
login.setIpAddress(ipAddress);
login.setIpSources(ipSource);
login.setNickname(loginUser.getNickname());
login.setLoginTime(new Date());
//查詢他上次得登錄時(shí)間設(shè)置為上次登錄時(shí)間
//這個(gè)時(shí)間應(yīng)該設(shè)置到redis中 每次登錄就存入redis作為上次登錄時(shí)間 并且每次更新
//存入表
userLoginService.save(login);
}
}- MyAuthenticationFailureHandler(自定義登陸失敗處理)
package com.lzj.handler.auth;
import com.alibaba.fastjson.JSON;
import com.lzj.enums.ResultInfo;
import com.lzj.utils.Result;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* <p>
* 自定義登陸失敗處理
* </p>
*
* @author:雷子杰
* @date:2022/8/6
*/
@Component
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
//來到登錄失敗處理器
//這個(gè)返回可以封裝一下 就2個(gè)不用了
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(JSON.toJSONString(Result.error()
.setCode(ResultInfo.LOGIN_FAILED.getCode())
.setMessage(ResultInfo.LOGIN_FAILED.getMessage())));
}
}- LogoutSuccessHandlerImpl(自定義認(rèn)證注銷處理)
package com.lzj.handler.auth;
import com.alibaba.fastjson.JSON;
import com.lzj.utils.Result;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* <p>
* 自定義認(rèn)證注銷處理
* </p>
*
* @author:雷子杰
* @date:2022/8/6
*/
@Component
public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler {
@Override
public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
httpServletResponse.setContentType("application/json;charset=UTF-8");
httpServletResponse.getWriter().write(JSON.toJSONString(Result.ok().setMessage("注銷成功")));
}
}- 自定義登錄賬號(hào)密碼處理
package com.lzj.handler.auth;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lzj.exception.security.MyAuthenticationException;
import com.lzj.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
/**
* <p>
* 自定義登錄賬號(hào)密碼處理
* </p>
*
* @author:雷子杰
* @date:2022/8/6
*/
public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Reference
private UserService userService;
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
//攜帶頭要是json格式得application/json;charset=UTF-8
//前后端分離 這里是接收的是json串
if (request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE)
|| request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)){
ObjectMapper objectMapper = new ObjectMapper();
//token對(duì)象
UsernamePasswordAuthenticationToken authRequest = null;
//取authenticationBean
Map<String, String> authenticationBean = null;
//用try with resource,方便自動(dòng)釋放資源
//用try with resource,方便自動(dòng)釋放資源
try (InputStream is = request.getInputStream()) {
//字符串轉(zhuǎn)集合
authenticationBean = objectMapper.readValue(is, Map.class);
} catch (IOException e) {
//將異常放到自定義的異常類中
System.out.println(e.getMessage());
throw new MyAuthenticationException(e.getMessage());
}
try {
if (!authenticationBean.isEmpty()) {
//獲得賬號(hào)、密碼
String username = authenticationBean.get(SPRING_SECURITY_FORM_USERNAME_KEY);
String password = authenticationBean.get(SPRING_SECURITY_FORM_PASSWORD_KEY);
//可以驗(yàn)證賬號(hào)、密碼
// System.out.println("username = " + username);
// System.out.println("password = " + password);
//檢測(cè)賬號(hào)、密碼是否存在
if (userService.checkLogin(username, password)) {
//將賬號(hào)、密碼裝入U(xiǎn)sernamePasswordAuthenticationToken中
authRequest = new UsernamePasswordAuthenticationToken(username, password);
setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
}
} catch (AuthenticationException e) {
e.printStackTrace();
throw new MyAuthenticationException(e.getMessage());
}
throw new MyAuthenticationException("用戶或者密碼錯(cuò)誤");
}
return this.attemptAuthentication(request,response);
}
}- UserServiceImpl
@Component
@Service
@Slf4j
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
private UserMapper userMapper;
@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
/**
* 檢測(cè)用戶賬號(hào)密碼是否存在
* @param username 用戶名
* @param password 密碼
* @return 是否存在
*/
@Override
public boolean checkLogin(String username, String password) {
//從用戶表里面查出用戶 然得到加密的密碼
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("password").eq("username", username);
User user = userMapper.selectOne(wrapper);
if(user==null){
return false;
}
//這個(gè)是加密后的密碼 在數(shù)據(jù)庫里面
String userPassword = user.getPassword();
//用加密匹配這個(gè) 能匹配返回true 不能返回false
return bCryptPasswordEncoder.matches(password, userPassword);
}
}- 自定義登陸處理
package com.lzj.handler.auth;
import com.alibaba.fastjson.JSON;
import com.lzj.utils.Result;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* <p>
* 自定義登錄處理
* </p>
*
* @author:雷子杰
* @date:2022/8/6
*/
@Component
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {
/**
*/
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(
JSON.toJSONString(Result.error().setMessage("請(qǐng)登錄")));
}
}- 自定義權(quán)限處理
package com.lzj.handler.auth;
import com.alibaba.fastjson.JSON;
import com.lzj.utils.Result;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* <p>
* 自定義權(quán)限處理
* </p>
*
* @author:雷子杰
* @date:2022/8/6
*/
@Component
public class MyAccessDeniedHandler implements AccessDeniedHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(JSON.toJSONString(Result.error().setMessage("沒有權(quán)限")));
}
}自定義認(rèn)證數(shù)據(jù)源
- 定義Security里的數(shù)據(jù)源實(shí)體類
package com.lzj.config.security;
import com.lzj.entity.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
/**
* <p>
* Security里的數(shù)據(jù)源實(shí)體類
* </p>
*
* @author:雷子杰
* @date:2022/8/6
*/
public class UserAuth implements UserDetails {
@Override
public String toString() {
return "UserAuth{" +
"user=" + user +
", authorities=" + authorities +
'}';
}
private User user;
private Collection<? extends GrantedAuthority> authorities;
public UserAuth() {
}
public UserAuth(User user, Collection<? extends GrantedAuthority> authorities) {
this.user = user;
this.authorities = authorities;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public void setAuthorities(Collection<? extends GrantedAuthority> authorities) {
this.authorities = authorities;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}- 自定義數(shù)據(jù)源配置
package com.lzj.config.security;
import com.lzj.entity.User;
import com.lzj.service.UserService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
/**
* <p>
* 自定義數(shù)據(jù)源配置
* </p>
*
* @author:雷子杰
* @date:2022/8/6
*/
@Service
public class MyUserDetailsService implements UserDetailsService {
@Reference
private UserService userService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if(username.isEmpty()){
throw new UsernameNotFoundException("用戶名為空");
}
//根據(jù)用戶名找user
User user = userService.getUserByUsername(username);
if(user!=null){
List<GrantedAuthority> authorities=new ArrayList<>();
//根據(jù)用戶名查找用戶角色列表
List<String> roles = userService.listUserRolesByUsername(username);
//這樣寫減少對(duì)象指針 好一點(diǎn)
SimpleGrantedAuthority simpleGrantedAuthority=null;
for (String role :roles){
simpleGrantedAuthority =new SimpleGrantedAuthority(role);
authorities.add(simpleGrantedAuthority);
}
UserAuth userAuth=new UserAuth();
userAuth.setUser(user);
userAuth.setAuthorities(authorities);
return userAuth;
} else {
throw new UsernameNotFoundException("沒有該用戶");
}
}
}- UserServiceImpl
@Component
@Service
@Slf4j
@Transactional
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
private UserMapper userMapper;
/**
* 通過用戶名獲取用戶信息
* @param username 用戶名
* @return 查詢到的信息
*/
@Override
public User getUserByUsername(String username) {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("username", username);
User user = userMapper.selectOne(wrapper);
return user;
}
/**
* 根據(jù)用戶名查找權(quán)限信息
* @param username 用戶名
* @return 權(quán)限信息集合
*/
@Override
public List<String> listUserRolesByUsername(String username) {
List<String> roles = userMapper.listUserRolesByUsername(username);
return roles;
}
}- UserMapper.xml
!-- 根據(jù)用戶名查找該用戶的權(quán)限-->
<select id="listUserRolesByUsername" resultType="java.lang.String">
select tb_role.role_name
from tb_role, tb_user, tb_role_user
where tb_role.role_id=tb_role_user.role_id
and tb_user.user_id=tb_role_user.user_id
and tb_user.username=#{username}
</select>自定義異常處理
- MyaccessDeniedException
package com.lzj.exception.security;
import org.springframework.security.access.AccessDeniedException;
/**
* <p>
*
* </p>
*
* @author:雷子杰
* @date:2022/8/6
*/
public class MyaccessDeniedException extends AccessDeniedException {
public MyaccessDeniedException(String msg) {
super(msg);
}
}- MyAuthenticationException
package com.lzj.exception.security;
import org.springframework.security.core.AuthenticationException;
/**
* <p>
*
* </p>
*
* @author:雷子杰
* @date:2022/8/6
*/
public class MyAuthenticationException extends AuthenticationException {
public MyAuthenticationException(String msg) {
super(msg);
}
}權(quán)限判斷與獲?。ú灰欢ㄒ砑樱?/h3>
package com.lzj.config.security;
import com.alibaba.fastjson.JSON;
import com.lzj.entity.Api;
import com.lzj.exception.security.MyaccessDeniedException;
import com.lzj.service.UserService;
import com.lzj.utils.RedisUtil;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
/**
* <p>
* 權(quán)限判斷與獲取
* </p>
*
* @author:雷子杰
* @date:2022/8/6
*/
@Component
public class DynamicPermission {
private final static String PERMISSION_KEY="PERMISSION_KEY";
@Autowired
private RedisUtil redisUtil;
@Autowired
HttpServletRequest request;
@Reference
private UserService userService;
/**
* 判斷有訪問API的權(quán)限
* @param authentication
* @return
* @throws MyaccessDeniedException
*/
public boolean checkPermisstion(Authentication authentication) throws MyaccessDeniedException, IOException {
String name = authentication.getName();
//如果是匿名用戶 給匿名用戶get權(quán)限 查看
if(name.equals("anonymousUser")){
String method = request.getMethod();
if(method.equals("GET")){
return true;
}else{
throw new MyaccessDeniedException("非法操作!");
}
}
//獲取當(dāng)前用戶認(rèn)證信息
Object principal = authentication.getPrincipal();
if(principal instanceof UserDetails) {
UserDetails userDetails = (UserDetails) principal;
//獲取到用戶名登陸時(shí)輸入表單的用戶名
String username = userDetails.getUsername();
//通過賬號(hào)獲取資源鑒權(quán)查看當(dāng)前用戶下的權(quán)限信息表
//這個(gè)鑒權(quán)經(jīng)查詢常要用到 可以加入緩存
//免得
List<Api> apiUrls = getApiUrlByUserName(username);
//AntPathMatcher antPathMatcher = new AntPathMatcher();
//當(dāng)前訪問路徑
String requestURI = request.getRequestURI();
//提交類型
String urlMethod = request.getMethod();
//判斷當(dāng)前路徑在不在訪問資源中
boolean hashAntPath=false;
int hasMethod=-1;
AntPathMatcher pathMatcher = new AntPathMatcher();
//判斷當(dāng)前訪問路徑在不在權(quán)限表里面
for(Api item :apiUrls){
if(pathMatcher.match(item.getUrl(), requestURI)){
hashAntPath=true;
}
hasMethod=item.getMethod().toUpperCase().indexOf(urlMethod.toUpperCase());
if(hashAntPath && hasMethod!=-1){
break;
}
}
boolean res=hashAntPath && hasMethod!=-1;
if(res){
return res;
} else {
throw new MyaccessDeniedException("用戶權(quán)限不足!");
}
} else{
throw new MyaccessDeniedException("不是UserDetails類型!");
}
}
private List<Api> getApiUrlByUserName(String username) {
List<Api> urlApis=null;
String key= PERMISSION_KEY+"_"+username;
String api = (String) redisUtil.get(key);
//String api = (String) redisTemplate.opsForValue().get(key);
if(api!=null && api!="" ){
//urlApis= JSON.parseObject(api, List.class);
// System.out.println("緩存中"+urlApis);
// return urlApis;
urlApis= JSON.parseArray(api, Api.class);
System.out.println(urlApis);
return urlApis;
}
//獲取該用戶的api權(quán)限
List<Api> apis = userService.getApiUrlByUserName(username);
//加入緩存然后設(shè)置過期時(shí)間為半個(gè)小時(shí)
redisUtil.set(key,JSON.toJSONString(apis),1800);
//redisTemplate.opsForValue().set(key, JSON.toJSONString(apis), Duration.ofSeconds(1800L));
return apis;
}
}
package com.lzj.config.security;
import com.alibaba.fastjson.JSON;
import com.lzj.entity.Api;
import com.lzj.exception.security.MyaccessDeniedException;
import com.lzj.service.UserService;
import com.lzj.utils.RedisUtil;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
/**
* <p>
* 權(quán)限判斷與獲取
* </p>
*
* @author:雷子杰
* @date:2022/8/6
*/
@Component
public class DynamicPermission {
private final static String PERMISSION_KEY="PERMISSION_KEY";
@Autowired
private RedisUtil redisUtil;
@Autowired
HttpServletRequest request;
@Reference
private UserService userService;
/**
* 判斷有訪問API的權(quán)限
* @param authentication
* @return
* @throws MyaccessDeniedException
*/
public boolean checkPermisstion(Authentication authentication) throws MyaccessDeniedException, IOException {
String name = authentication.getName();
//如果是匿名用戶 給匿名用戶get權(quán)限 查看
if(name.equals("anonymousUser")){
String method = request.getMethod();
if(method.equals("GET")){
return true;
}else{
throw new MyaccessDeniedException("非法操作!");
}
}
//獲取當(dāng)前用戶認(rèn)證信息
Object principal = authentication.getPrincipal();
if(principal instanceof UserDetails) {
UserDetails userDetails = (UserDetails) principal;
//獲取到用戶名登陸時(shí)輸入表單的用戶名
String username = userDetails.getUsername();
//通過賬號(hào)獲取資源鑒權(quán)查看當(dāng)前用戶下的權(quán)限信息表
//這個(gè)鑒權(quán)經(jīng)查詢常要用到 可以加入緩存
//免得
List<Api> apiUrls = getApiUrlByUserName(username);
//AntPathMatcher antPathMatcher = new AntPathMatcher();
//當(dāng)前訪問路徑
String requestURI = request.getRequestURI();
//提交類型
String urlMethod = request.getMethod();
//判斷當(dāng)前路徑在不在訪問資源中
boolean hashAntPath=false;
int hasMethod=-1;
AntPathMatcher pathMatcher = new AntPathMatcher();
//判斷當(dāng)前訪問路徑在不在權(quán)限表里面
for(Api item :apiUrls){
if(pathMatcher.match(item.getUrl(), requestURI)){
hashAntPath=true;
}
hasMethod=item.getMethod().toUpperCase().indexOf(urlMethod.toUpperCase());
if(hashAntPath && hasMethod!=-1){
break;
}
}
boolean res=hashAntPath && hasMethod!=-1;
if(res){
return res;
} else {
throw new MyaccessDeniedException("用戶權(quán)限不足!");
}
} else{
throw new MyaccessDeniedException("不是UserDetails類型!");
}
}
private List<Api> getApiUrlByUserName(String username) {
List<Api> urlApis=null;
String key= PERMISSION_KEY+"_"+username;
String api = (String) redisUtil.get(key);
//String api = (String) redisTemplate.opsForValue().get(key);
if(api!=null && api!="" ){
//urlApis= JSON.parseObject(api, List.class);
// System.out.println("緩存中"+urlApis);
// return urlApis;
urlApis= JSON.parseArray(api, Api.class);
System.out.println(urlApis);
return urlApis;
}
//獲取該用戶的api權(quán)限
List<Api> apis = userService.getApiUrlByUserName(username);
//加入緩存然后設(shè)置過期時(shí)間為半個(gè)小時(shí)
redisUtil.set(key,JSON.toJSONString(apis),1800);
//redisTemplate.opsForValue().set(key, JSON.toJSONString(apis), Duration.ofSeconds(1800L));
return apis;
}
}總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
您可能感興趣的文章:
- SpringBoot集成SpringSecurity安全框架方式
- SpringBoot集成Swagger使用SpringSecurity控制訪問權(quán)限問題
- 如何在SpringBoot項(xiàng)目中集成SpringSecurity進(jìn)行權(quán)限管理
- SpringBoot集成Spring security JWT實(shí)現(xiàn)接口權(quán)限認(rèn)證
- Springboot WebFlux集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的示例
- Springboot集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的步驟詳解
- springboot集成springsecurity 使用OAUTH2做權(quán)限管理的教程
相關(guān)文章
使用hibernate和struts2實(shí)現(xiàn)分頁功能的示例
本篇文章主要介紹了使用hibernate和struts2實(shí)現(xiàn)分頁功能,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-01-01
Springboot實(shí)現(xiàn)頁面間跳轉(zhuǎn)功能
這篇文章主要介紹了Springboot實(shí)現(xiàn)頁面間跳轉(zhuǎn)功能,本文給大家分享兩種方式,方法一和方法二是不沖突的,但是通常情況下如果用方法二addViewControllers,需要把方法一所寫的Controller類給注釋掉,需要的朋友可以參考下2023-10-10
java GUI實(shí)現(xiàn)ATM機(jī)系統(tǒng)(3.0版)
這篇文章主要為大家詳細(xì)介紹了java GUI實(shí)現(xiàn)ATM機(jī)系統(tǒng)(3.0版),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-03-03
詳解Struts2中json 相互引用死循環(huán)解決辦法
本篇文章主要介紹詳解Struts2中json 相互引用死循環(huán)解決辦法,具有一定的參考價(jià)值,有興趣的可以了解一下。2017-01-01

