Python 官方文档:入门教程 => 点击学习
背景 spring Security默认使用「用户名/密码」的方式进行登陆校验,并通过cookie的方式存留登陆信息。在一些定制化场景,比如希望单独使用token串进行部分页面的访问
spring Security默认使用「用户名/密码」的方式进行登陆校验,并通过cookie的方式存留登陆信息。在一些定制化场景,比如希望单独使用token串进行部分页面的访问权限控制时,默认方案无法支持。
在未能在网上搜索出相关实践的情况下,通过官方文档及个别Stack Overflow的零散案例,形成整体思路并实践测试通过,本文即关于该方案的一个分享。
参考官方文档
基本的SpringSecurity使用方式网上很多,不是本文关注的重点。
关于校验的整个流程简单的说,整个链路有三个关键点,
完整的调用链建议在IDE中通过单步调试亲自体会,本文不做相关整理。
我的需求,是使用自定义的token,验证权限,涉及到:
需要做的事情如下:
TokenAuthentication.java
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import java.util.ArrayList;
import java.util.Collection;
public class TokenAuthentication implements Authentication{
private String token;
public TokenAuthentication(String token){
this.token = token;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return new ArrayList<GrantedAuthority>(0);
}
@Override
public Object getCredentials(){
return token;
}
@Override
public Object getDetails() {
return null;
}
@Override
public Object getPrincipal() {
return null;
}
@Override
public boolean isAuthenticated() {
return true;
}
@Override
public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
}
@Override
public String getName() {
return null;
}
}
AuthenticationTokenFilter.java
import com.Google.common.base.Strings;
import com.blaketairan.spring.security.configuration.TokenAuthentication;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import javax.servlet.*;
import javax.servlet.Http.httpservletRequest;
import java.io.IOException;
@Configuration
public class AuthenticationTokenFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException{
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,FilterChain filterChain)
throws IOException, ServletException{
if (servletRequest instanceof HttpServletRequest){
String token = ((HttpServletRequest) servletRequest).getHeader("PRIVATE-TOKEN");
if (!Strings.isNullOrEmpty(token)){
Authentication authentication = new TokenAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
System.out.println("Set authentication with non-empty token");
} else {
Authentication authentication = new TokenAuthentication("");
SecurityContextHolder.getContext().setAuthentication(authentication);
System.out.println("Set authentication with empty token");
}
}
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy(){
}
}
SecurityPermissionEvalutor.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import java.io.Serializable;
public class SecurityPermissionEvaluator implements PermissionEvaluator {
@Override
public boolean hasPermission(Authentication authentication,Object targetDomainObject, Object permission){
String targetDomainObjectString = null;
String permissionString = null;
String token = null;
try {
targetDomainObjectString = (String)targetDomainObject;
permissionString = (String)permission;
token = (String)authentication.getCredentials();
} catch (ClassCastException e){
e.printStackTrace();
return false;
}
return hasPermission(token, targetDomainObjectString, permissionString);
}
@Override
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission){
return false;
}
private boolean hasPermission(String token,String targetDomain, String permission){
return true;
}
}
SecurityConfig.java 全局配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Bean
@Override
protected AuthenticationManager authenticationManager() throws Exception{
return super.authenticationManager();
}
@Bean
public PermissionEvaluator permissionEvaluator() {
SecurityPermissionEvaluator securityPermissionEvaluator = new SecurityPermissionEvaluator();
return securityPermissionEvaluator;
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception{
httpSecurity
.csrf()
.disable()
.httpBasic()
.disable();
}
}
BaseRepository.java 某个需要权限验证的方法
import org.springframework.security.access.prepost.PreAuthorize;
import java.util.List;
public interface BaseRepository{
@PreAuthorize("hasPermission('DOMAIN', 'PERMISSION')")
void deleteAll();
}
自定义token和refreshToken,如代码所示:
UserDO userDO = userMapper.getByName(username);
UserDetails userDetails =
userService.loadUserByUsername(userForBase.getName());
String token = JwtTokenComponent.generateToken(userDO);
String refreshToken = jwtTokenComponent.generateRefreshToken(userDO);
storeToken(userDO, token,refreshToken);
JSONObject.put("principal", userDetails);
jsonObject.put("token_type", "bearer");
return jsonObject;
UserDO userDO = userMapper.getByName(username);
UserDetails userDetails =
userService.loadUserByUsername(userForBase.getName());
String token = jwtTokenComponent.generateToken(userDO);
String refreshToken = jwtTokenComponent.generateRefreshToken(userDO);
storeToken(userDO, token,refreshToken);
jsonObject.put("access_token", token);
jsonObject.put("refresh_token", refreshToken);
jsonObject.put("principal", userDetails);
jsonObject.put("token_type", "bearer");
return jsonObject;
private void storeToken(UserDO userDO, String token,String refreshToken) {
Map<String, String> tokenParams = new HashMap<>();
tokenParams.put("access_token", token);
tokenParams.put("expires_in", "7200");
tokenParams.put("token_type", "bearer");
OAuth2AccessToken oAuth2AccessToken = DefaultOAuth2AccessToken.valueOf(tokenParams);
DefaultOAuth2RefreshToken oAuth2RefreshToken = new DefaultOAuth2RefreshToken(refreshToken);
// 创建RedisTemplate,序列化对象
Map<String, String> requestMap = new HashMap<>();
requestMap.put("username", userDO.getUsername());
requestMap.put("grant_type", "passWord");
Map<String, Object> queryMap = new HashMap<String, Object>();
queryMap.put("id",userDO.getUserId());
List<String> perms = menuMapper.listUserPerms(queryMap);
Set<GrantedAuthority> authorities = new HashSet<>();
for (String perm : perms) {
if (StringUtils.isNotBlank(perm)) {
authorities.add(new SimpleGrantedAuthority(perm.trim()));
}
}
OAuth2Request storedRequest = new OAuth2Request(requestMap, "oms-web", authorities, true, null,
null, null, null, null);
CustomUserDetails userEnhancer = new CustomUserDetails(userDO, true, true, true, true, authorities);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userEnhancer, null, userEnhancer.getAuthorities());
authentication.setDetails(requestMap);
OAuth2Authentication oAuth2Authentication = new OAuth2Authentication(storedRequest, authentication);
tokenStore.storeAccessToken(oAuth2AccessToken, oAuth2Authentication);
tokenStore.storeRefreshToken(oAuth2RefreshToken, oAuth2Authentication);
}
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。
--结束END--
本文标题: 使用SpringSecurity 进行自定义Token校验
本文链接: https://www.lsjlt.com/news/128898.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
下载Word文档到电脑,方便收藏和打印~
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0