SpringBoot整合SpringSecurity权限控制(动态拦截url+单点登录)
Posted 不会写文档的程序员
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringBoot整合SpringSecurity权限控制(动态拦截url+单点登录)相关的知识,希望对你有一定的参考价值。
Spring Security是一个功能强大且可高度自定义的身份验证和访问控制框架。它是保护基于Spring的应用程序的事实上的标准。
Spring Security是一个专注于为Java应用程序提供身份验证和授权的框架。与所有Spring项目一样,Spring Security的真正强大之处在于它可以轻松扩展以满足自定义要求。
一、项目搭建
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
登录拦截全局配置
@Configuration
public class WebSecurityConfigure extends WebSecurityConfigurerAdapter
@Resource
private UrlAuthenticationEntryPoint authenticationEntryPoint; //自定义未登录时:返回状态码401
@Resource
private UrlAuthenticationSuccessHandler authenticationSuccessHandler; //自定义登录成功处理器并生成token:响应状态码200及token
@Resource
private UrlAuthenticationFailureHandler authenticationFailureHandler; //自定义登录失败处理器:返回状态码402
@Resource
private UrlAccessDeniedHandler accessDeniedHandler; //自定义权限不足处理器:返回状态码403
@Resource
private UrlLogoutSuccessHandler logoutSuccessHandler; //自定义注销成功处理器:返回状态码200
@Resource
private SelfAuthenticationProvider authenticationProvider; //自定义登录认证
@Resource
private SelfFilterInvocationSecurityMetadataSource filterInvocationSecurityMetadataSource; //动态获取url权限配置
@Resource
private SelfAccessDecisionManager accessDecisionManager; //自定义权限判断管理器
@Resource
private AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> authenticationDetailsSource; //身份验证详细信息源
@Resource
private JwtAuthorizationTokenFilter authorizationTokenFilter; //JwtToken解析并生成authentication身份信息过滤器
@Override
public void configure(WebSecurity web)
// web.ignoring().antMatchers("/connect/**"); //无条件允许访问
web.ignoring().antMatchers("/common/**"); //无条件允许访问
@Override
protected void configure(AuthenticationManagerBuilder auth)
auth.authenticationProvider(authenticationProvider); //自定义登录认证
@Override
protected void configure(HttpSecurity http) throws Exception
// 关闭csrf验证(防止跨站请求伪造攻击)
http.csrf().disable();
// JwtToken解析并生成authentication身份信息过滤器
http.addFilterBefore(authorizationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// 未登录时:返回状态码401
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint);
// 无权访问时:返回状态码403
http.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
// url权限认证处理
http.antMatcher("/**").authorizeRequests()
// .antMatchers("/security/user/**").hasRole("ADMIN") //需要ADMIN角色才可以访问
// .antMatchers("/connect").hasIpAddress("127.0.0.1") //只有ip[127.0.0.1]可以访问'/connect'接口
.anyRequest() //其他任何请求
.authenticated() //都需要身份认证
.withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>()
@Override
public <O extends FilterSecurityInterceptor> O postProcess(O o)
o.setSecurityMetadataSource(filterInvocationSecurityMetadataSource); //动态获取url权限配置
o.setAccessDecisionManager(accessDecisionManager); //权限判断
return o;
);
// 将session策略设置为无状态的,通过token进行登录认证
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// 开启自动配置的登录功能
http.formLogin() //开启登录
// .loginPage("/login") //登录页面(前后端不分离)
.loginProcessingUrl("/nonceLogin") //自定义登录请求路径(post)
.usernameParameter("username").passwordParameter("password") //自定义登录用户名密码属性名,默认为username和password
// .successForwardUrl("/index") //登录成功后的url(post,前后端不分离)
// .failureForwardUrl("/error") //登录失败后的url(post,前后端不分离)
.successHandler(authenticationSuccessHandler) //验证成功处理器(前后端分离):生成token及响应状态码200
.failureHandler(authenticationFailureHandler) //验证失败处理器(前后端分离):返回状态码402
.authenticationDetailsSource(authenticationDetailsSource); //身份验证详细信息源(登录验证中增加额外字段)
// 开启自动配置的注销功能
http.logout() //用户注销, 清空session
.logoutUrl("/nonceLogout") //自定义注销请求路径
// .logoutSuccessUrl("/bye") //注销成功后的url(前后端不分离)
.logoutSuccessHandler(logoutSuccessHandler); //注销成功处理器(前后端分离):返回状态码200
JwtToken解析并生成authentication身份信息过滤器
@SuppressWarnings("unchecked")
@Slf4j
@Component
public class JwtAuthorizationTokenFilter extends OncePerRequestFilter
@Value("$jwt.token-header-key")
private String tokenHeaderKey; //token请求头Key
@Value("$jwt.token-prefix")
private String tokenPrefix; //token前缀
@Value("$jwt.token-secret")
private String tokenSecret; //token秘钥
/**
* 解析token并生成authentication身份信息
*/
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException
String token = request.getHeader(tokenHeaderKey);
log.info("JwtAuthorizationTokenFilter >> token:", token);
if (null == token || !token.startsWith(tokenPrefix + " "))
chain.doFilter(request, response);
return;
Claims claims;
try
// 解析token
claims = Jwts.parser().setSigningKey(tokenSecret).parseClaimsJws(token.replace(tokenPrefix + " ", "")).getBody();
catch (Exception e)
log.error("JwtToken validity!! error=", e.getMessage());
chain.doFilter(request, response);
return;
String username = claims.getSubject();
List<String> roles = claims.get("role", List.class);
List<SimpleGrantedAuthority> authorities = roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
if (null != username)
// 生成authentication身份信息
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, null, authorities);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
自定义登录认证
@Slf4j
@Component
public class SelfAuthenticationProvider implements AuthenticationProvider
@Resource
private SelfUserDetailsService selfUserDetailsService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
log.info("authentication >> ", JSONObject.toJSONString(authentication, SerializerFeature.WriteMapNullValue));
CustomWebAuthenticationDetails customWebAuthenticationDetails = (CustomWebAuthenticationDetails) authentication.getDetails(); //获取身份验证详细信息
// String remoteAddress = customWebAuthenticationDetails.getRemoteAddress();
// String sessionId = customWebAuthenticationDetails.getSessionId();
// System.out.println("remoteAddress >> " + remoteAddress);
// System.out.println("sessionId >> " + sessionId);
// System.out.println("details >> " + JSONObject.toJSONString(customWebAuthenticationDetails, SerializerFeature.WriteMapNullValue));
System.out.println("macAddress >> " + customWebAuthenticationDetails.getMacAddress()); //用于校验mac地址白名单(这里只是打个比方,登录验证中增加的额外字段)
String username = (String) authentication.getPrincipal(); //表单输入的用户名
String password = (String) authentication.getCredentials(); //表单输入的密码
UserDetails userInfo = selfUserDetailsService.loadUserByUsername(username);
boolean matches = new BCryptPasswordEncoder().matches(password, userInfo.getPassword()); //校验用户名密码
if (!matches)
throw new BadCredentialsException("The password is incorrect!!");
return new UsernamePasswordAuthenticationToken(username, userInfo.getPassword(), userInfo.getAuthorities());
@Override
public boolean supports(Class<?> aClass)
return true;
自定义用户认证
@Component
public class SelfUserDetailsService implements UserDetailsService
@Resource
private UserService userService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
SelfUserDetails userInfo = new SelfUserDetails();
userInfo.setUsername(username); //任意登录用户名
String password = userService.findPasswordByUsernameAfterValidTime(username);
if (ObjectUtils.isEmpty(password))
throw new UsernameNotFoundException("User name" + username + "not find!!");
userInfo.setPassword(password); //从数据库获取密码
Set<SimpleGrantedAuthority> authoritiesSet = new HashSet<>();
List<String> roles = userService.findRoleNameByUsername(username);
for (String roleName : roles)
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(roleName); //用户拥有的角色
authoritiesSet.add(simpleGrantedAuthority);
userInfo.setAuthorities(authoritiesSet);
return userInfo;
自定义web身份验证详细信息(用于登录验证中增加额外参数)
class CustomWebAuthenticationDetails extends WebAuthenticationDetails implements Serializable
private String macAddress;
CustomWebAuthenticationDetails(HttpServletRequest httpServletRequest)
super(httpServletRequest);
// Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
// while (headerNames.hasMoreElements())
// String s = headerNames.nextElement();
// String header = httpServletRequest.getHeader(s);
// System.out.println(s + ": " + header);
//
macAddress = httpServletRequest.getParameter("macAddress");
String getMacAddress()
return macAddress;
自定义身份验证详细信息源
@Component
public class CustomAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails>
@Override
public WebAuthenticationDetails buildDetails(HttpServletRequest httpServletRequest)
return new CustomWebAuthenticationDetails(httpServletRequest);
动态获取url权限配置
@Slf4j
@Component
public class SelfFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource
@Resource
private UserService userService;
private AntPathMatcher antPathMatcher = new AntPathMatcher();
@Override
public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException
Set<ConfigAttribute> set = new HashSet<>();
// 获取请求地址
String requestUrl = ((FilterInvocation) o).getRequestUrl();
log.info("requestUrl >> ", requestUrl);
List<String> menuUrl = userService.findAllMenuUrl();
for (String url : menuUrl)
if (antPathMatcher.match(url, requestUrl))
List<String> roleNames = userService.findRoleNameByMenuUrl(url); //当前请求需要的权限
roleNames.forEach(roleName ->
SecurityConfig securityConfig = new SecurityConfig(roleName);
set.add(securityConfig);
);
if (ObjectUtils.isEmpty(set))
return SecurityConfig.createList("ROLE_LOGIN");
return set;
@Override
public Collection<ConfigAttribute> getAllConfigAttributes()
return null;
@Override
public boolean supports(Class<?> aClass)
return FilterInvocation.class.isAssignableFrom(aClass);
自定义权限判断管理器
@Slf4j
@Component
public class SelfAccessDecisionManager implements AccessDecisionManager
@Override
public void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException
// 当前请求需要的权限
log.info("collection:", collection);
// 当前用户所具有的权限
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
log.info("principal: authorities:", authentication.getPrincipal().toString(), authorities);
for (ConfigAttribute configAttribute : collection)
// 当前请求需要的权限
String needRole = configAttribute.getAttribute();
if ("ROLE_LOGIN".equals(needRole))
if (authentication instanceof AnonymousAuthenticationToken)
throw new BadCredentialsException("Not logged in!!");
else
return;
// 当前用户所具有的权限
for (GrantedAuthority grantedAuthority : authorities)
// 包含其中一个角色即可访问
if (grantedAuthority.getAuthority().equals(needRole))
return;
throw new AccessDeniedException("SimpleGrantedAuthority!!");
@Override
public boolean supports(ConfigAttribute configAttribute)
return true;
@Override
public boolean supports(Class<?> aClass)
return true;
自定义未登录时:返回状态码401
@Component
public class UrlAuthenticationEntryPoint implements AuthenticationEntryPoint
@Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException
UrlResponse response = new UrlResponse();
response.setSuccess(false);
response.setCode("401");
response.setMessage(e.getMessage());
response.setData(null);
httpServletResponse.setStatus(401);
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("text/html;charset=UTF-8");
httpServletResponse.getWriter().write(GsonUtil.GSON.toJson(response));
自定义登录成功处理器:返回状态码200
@Component
public class UrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler
@Value("$jwt.token-header-key")
private String tokenHeaderKey; //token响应头Key
@Value("$jwt.token-prefix")
private String tokenPrefix; //token前缀
@Value("$jwt.token-secret")
private String tokenSecret; //token秘钥
@Value("$jwt.token-expiration")
private Long tokenExpiration; //token过期时间
@Resource
private UserService userService;
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException
httpServletResponse.setCharacterEncoding("UTF-8");
UrlResponse response = new UrlResponse();
response.setSuccess(true);
response.setCode("200");
response.setMessage("Login Success!");
String username = (String) authentication.getPrincipal(); //表单输入的用户名
Map<String, Object> userInfo = userService.findMenuInfoByUsername(username, response); //用户可访问的菜单信息
response.setData(userInfo);
// 生成token并设置响应头
Claims claims = Jwts.claims();
claims.put("role", authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()));
String token = Jwts.builder()
.setClaims(claims)
.setSubject(username) //设置用户名
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration)) //设置token过期时间
.signWith(SignatureAlgorithm.HS512, tokenSecret).compact(); //设置token签名算法及秘钥
httpServletResponse.addHeader(tokenHeaderKey, tokenPrefix + " " + token); //设置token响应头
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("text/html;charset=UTF-8");
httpServletResponse.getWriter().write(GsonUtil.GSON.toJson(response));
自定义登录失败处理器:返回状态码402
@SuppressWarnings("Duplicates")
@Component
public class UrlAuthenticationFailureHandler implements AuthenticationFailureHandler
@Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException
UrlResponse response = new UrlResponse();
response.setSuccess(false);
response.setCode("402");
response.setMessage(e.getMessage());
response.setData(null);
httpServletResponse.setStatus(402);
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("text/html;charset=UTF-8");
httpServletResponse.getWriter().write(GsonUtil.GSON.toJson(response));
自定义权限不足处理器:返回状态码403
@Component
public class UrlAccessDeniedHandler implements AccessDeniedHandler
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException
UrlResponse response = new UrlResponse();
response.setSuccess(false);
response.setCode("403");
response.setMessage(e.getMessage());
response.setData(null);
httpServletResponse.setStatus(403);
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("text/html;charset=UTF-8");
httpServletResponse.getWriter().write(GsonUtil.GSON.toJson(response));
自定义注销成功处理器:返回状态码200
@Component
public class UrlLogoutSuccessHandler implements LogoutSuccessHandler
@Override
public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException
UrlResponse response = new UrlResponse();
response.setSuccess(true);
response.setCode("200");
response.setMessage("Logout Success!!");
response.setData(null);
httpServletResponse.setCharacterEncoding("UTF-8");
httpServletResponse.setContentType("text/html;charset=UTF-8");
httpServletResponse.getWriter().write(GsonUtil.GSON.toJson(response));
application.yml
server:
port: 8018
# servlet:
# session:
# timeout: 6h
spring:
# main:
# web-application-type: none
# security:
# user:
# name: security_admin #设置默认登录用户名
# password: security_admin #设置默认登录密码 不设置会在控制台打印出,默认用户名是user
datasource:
url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2b8&autoReconnect=true&failOverReadOnly=false
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
hikari:
read-only: false
connection-timeout: 60000
idle-timeout: 60000
validation-timeout: 3000
max-lifetime: 60000
login-timeout: 5
maximum-pool-size: 60
minimum-idle: 10
jpa:
generate-ddl: false
show-sql: false
hibernate:
ddl-auto: none
database: mysql
open-in-view: true
jwt:
token-header-key: Authorization
token-prefix: NonceToken
token-expiration: 43200000 #12*60*60*1000 12小时
token-secret: NonceJwtSecret
数据库表结构设计
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for authority_user
-- ----------------------------
DROP TABLE IF EXISTS `authority_user`;
CREATE TABLE `authority_user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`username` varchar(255) DEFAULT NULL COMMENT '用户名',
`password` varchar(255) DEFAULT NULL COMMENT '密码',
`email` varchar(255) DEFAULT NULL COMMENT '邮箱',
`phone` varchar(255) DEFAULT NULL COMMENT '手机号',
`valid_time` varchar(255) DEFAULT NULL COMMENT '有效截止时间',
`update_time` varchar(255) DEFAULT NULL COMMENT '更新时间',
`remark` mediumtext COMMENT '备注',
`nickname` varchar(255) DEFAULT NULL COMMENT '昵称',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for authority_role
-- ----------------------------
DROP TABLE IF EXISTS `authority_role`;
CREATE TABLE `authority_role` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`role_name` varchar(255) DEFAULT NULL COMMENT '角色名称(必须以ROLE_起始命名)',
`role_name_CN` varchar(255) DEFAULT NULL COMMENT '角色名称中文',
`update_time` varchar(255) DEFAULT NULL COMMENT '更新时间',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for authority_menu
-- ----------------------------
DROP TABLE IF EXISTS `authority_menu`;
CREATE TABLE `authority_menu` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`url` varchar(255) DEFAULT NULL COMMENT '请求路径',
`menu_name` varchar(255) DEFAULT NULL COMMENT '菜单名称',
`parent_id` int(11) DEFAULT NULL COMMENT '父菜单id',
`update_time` varchar(255) DEFAULT NULL COMMENT '更新时间',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`url_pre` varchar(255) DEFAULT NULL COMMENT '路由(前端自己匹配用)',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=73 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for authority_user_role
-- ----------------------------
DROP TABLE IF EXISTS `authority_user_role`;
CREATE TABLE `authority_user_role` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`user_id` int(11) DEFAULT NULL,
`role_id` int(11) DEFAULT NULL,
`update_time` varchar(255) DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=63 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for authority_role_menu
-- ----------------------------
DROP TABLE IF EXISTS `authority_role_menu`;
CREATE TABLE `authority_role_menu` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`role_id` int(11) DEFAULT NULL,
`menu_id` int(11) DEFAULT NULL,
`update_time` varchar(255) DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=798 DEFAULT CHARSET=utf8;
链接:https://pan.baidu.com/s/1h74TOZDTMTwH0qCf1R96pA 提取码:7vhv
二、总结
以上就是今日分享的全部内容。希望能对大家的学习有所帮助,评论区留下“管用",记得三联哦。 还有其他知识分享,欢迎拜访链接: 首页
SpringSecurity解决跨域问题,在SpringBoot整合SprinSecurity中如何用前后端分离Ajax登录,Ajax登录返回状态200还是近error
先说说SpringSecurity如何实现前后端分离Ajax登录?
今天使用SpringBoot整合SpringSecurity中想使用Ajax替代SpringSecurit的Form表单提交,在这里我们的提交方式还是使用表单提交
http.formLogin().loginProcessingUrl("/authentication/form")
loginProcessingUrl方法表示你登录请求的地址,在这里SpringSecurity默认登录页面地址是/login ,填写了username与password 上送的地址就是loginProcessingUrl方法指定的地址,
如果你想使用Ajax登录+Token验证,或者是移动端不得不这样做的时候,那么你就不用管SpringSecurity的默认登录地址啦,只需要注意 在Ajax请求的时候 登录名必须是username字段
密码必须是 password字段 登录提交的地址就是loginProcessingUrl方法指定的路径/authentication/form
因为在SpringSecurity中处理账号密码登录的过滤器是UsernamePasswordAuthenticationFilter 而这个登录处理类里面写死了这两个字段的名称,如下图源码中所见:
public class UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter { // ~ Static fields/initializers // ===================================================================================== public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "username"; public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "password";
我测试的前端登录代码如下:
$.ajax({
url:"http://127.0.0.1/authentication/form",
timeout : 20000,
type:"post",
dataType:"json",
data:{
username:"088358",password:"123"
},
success:function(data){
alert(\'ok\')
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
alert("1 异步调用返回失败,XMLHttpResponse.readyState:"+XMLHttpRequest.readyState);
alert("2 异步调用返回失败,XMLHttpResponse.status:"+XMLHttpRequest.status);
alert("3 异步调用返回失败,textStatus:"+textStatus);
alert("4 异步调用返回失败,errorThrown:"+errorThrown);
}
})
后端在执行登录成功之后处理代码
后端在执行登录成功之后会回调AuthenticationSuccessHandler拦截器的onAuthenticationSuccess方法,我们只需要写一个类集成AuthenticationSuccessHandler就可以重写这个方法来生成token返回给前端了,Token如何生成,请看上一章jwtToken的使用 https://www.cnblogs.com/langjunnan/p/12464791.html ,这章不细说
@Component public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { // 登录成功之后 List<Object> functs = (List<Object>) authentication.getAuthorities();// 当前功能列表 String loginName = authentication.getName();// 登录名 Users obj = (Users) authentication.getPrincipal();// 用户信息 String token = JwtUtil.createToken(loginName, functs, obj);// 生成token response.setHeader(JwtUtil.TOKEN_HEADER, JwtUtil.TOKEN_PREFIX + token); response.setContentType("application/json;charset=utf-8"); response.setStatus(HttpServletResponse.SC_OK); PrintWriter pw = response.getWriter(); DTO dto = new DTO<>(); dto.setCode("000000"); dto.setMessage("认证通过"); String json=JsonUtil.set(dto); System.out.println(json); pw.println(json); // println 等于pw.flush()+pw.close(); } }
代码是没有问题的,但是由于跨域的问题Ajax是调用不成功的,
SpringSecurity中的跨域问题
之前写项目都是自己定义一个过滤器来解决跨域问题,但是这次过滤器不好用了,只能把跨域资源配置到SpringSecurity中了
代码如下
http.cors().configurationSource(CorsConfigurationSource())//允许跨域访问
/*跨域原*/ private CorsConfigurationSource CorsConfigurationSource() { CorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedOrigin("*"); //同源配置,*表示任何请求都视为同源,若需指定ip和端口可以改为如“localhost:8080”,多个以“,”分隔; corsConfiguration.addAllowedHeader("*");//header,允许哪些header,本案中使用的是token,此处可将*替换为token; corsConfiguration.addAllowedMethod("*"); //允许的请求方法,PSOT、GET等 ((UrlBasedCorsConfigurationSource) source).registerCorsConfiguration("/**",corsConfiguration); //配置允许跨域访问的url return source; }
以上是关于SpringBoot整合SpringSecurity权限控制(动态拦截url+单点登录)的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot系列八:SpringBoot整合消息服务(SpringBoot 整合 ActiveMQSpringBoot 整合 RabbitMQSpringBoot 整合 Kafka)
[SpringBoot系列]SpringBoot如何整合SSMP