Springboot+Spring-Security+JWT Sso单点登录
2021-03-04 04:29
标签:parameter nbsp ack 验证 就是 isa 自定义 form security+ 单点登录中目前比较流行的一种使用方式,就是springsecurity+jwt实现无状态下用户登录;下面是对于Spring-Security进行单点登录使用token来进行交互的一种方式。第一次写博客请多多指教如果有更好的方式或者是错误的点麻烦请指教。 Spring-Security的主要几个实现类 WebSecurityConfigurerAdapter这个类主要是用来对Spring Security的请求,拦截等进行一些配置 ExcpeitonMappingAuthenticationFailureHandler 这个类主要是对登录失败进行处理 SaveRequestAwareAuthenticationSucessHandler 这个类主要是对登录成功进行处理 UserDetailsService 这个类主要是用于对权限的校验还有登录的校验 BasicAuthenticationFilter 自定义拦截蓝主要是用于对token进行校验然后决定是否放行 从WebSecurityConfigurerAdapter进行请求,登录等请求进行配置 设置自定义登录跳转 对登录的账号密码进行对应的校验 对登录成功的类进行返回对应jwt加密过的token 登录失败的进行对应的处理 自定义拦截器进行token的校验 自定义拦截器Bean获取不到使用该方法进行获取 JWT进行简单的加密 Springboot+Spring-Security+JWT Sso单点登录 标签:parameter nbsp ack 验证 就是 isa 自定义 form security+ 原文地址:https://www.cnblogs.com/xiaoguifu/p/14367977.html@Component
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
LoginAuthenticationSuecssHandler loginAuthenticationSuecssHandler;
@Autowired
LoginAuthenticationFailHandler loginAuthenticationFailHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/authentication/require")
.loginProcessingUrl("/authentication/form")
.successHandler(loginAuthenticationSuecssHandler)
.failureHandler(loginAuthenticationFailHandler)
.and()
.authorizeRequests()//这个单词的意思是下面都是授权配置
.antMatchers("/authentication/require","/authentication/form").permitAll()//把授权信息放开
.anyRequest() //任何请求都被授权
.authenticated()//都需要身份认证
.and()
.addFilter(new AuthenticationTokenFilter(authenticationManager()))
.authorizeRequests()
.antMatchers(
"/",
"/*.html",
"/**/*.html",
"/**/*.css",
"/**/*.js"
).permitAll()
.and()
.csrf().disable();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/login.html");
}
}
@RestController
public class LoginController {
private Logger logger = LoggerFactory.getLogger(getClass());
private RequestCache requestCache = new HttpSessionRequestCache();
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@RequestMapping("/authentication/require")
@ResponseStatus(code = HttpStatus.UNAUTHORIZED)
public ResponseVo requireAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException {
logger.info("requireAuthentication:当前用户未登录:访问路径{}"+request.getServletPath());
SavedRequest savedRequest = requestCache.getRequest(request, response);
if (savedRequest != null){
String redirectUrl = savedRequest.getRedirectUrl();
if (StringUtils.endsWithIgnoreCase(redirectUrl, ".html")) {
logger.info("requireAuthentication:当前用户是PcWeb端请求:{}正在重定向");
response.sendRedirect("http://localhost:9050/login.html");
}
}
logger.info("requireAuthentication:访问的服务需要身份认证,请引导用户到登录页");
return ResponseMeaage.error(SysConstant.LOGIN_FALL);
}
}
@Component
public class MyUserDetailsService implements UserDetailsService {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
@Qualifier("dbUserMapper")
DbUserMapper dbUserMapper;
@Autowired
@Qualifier("httpServletRequest")
HttpServletRequest httpServletRequest;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if (!StringUtils.isEmpty(username)){
//自定义拦截器进行处理的时候会有bean注入不了的情况
if (dbUserMapper == null && httpServletRequest == null){
dbUserMapper = SpringUtils.getBean(DbUserMapper.class);
}
DbUser dbUser = dbUserMapper.selectOne(new QueryWrapperpublic class LoginAuthenticationSuecssHandler extends SavedRequestAwareAuthenticationSuccessHandler {
@Autowired
private ObjectMapper objectMapper;
private Logger logger = LoggerFactory.getLogger(getClass());
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
String header = request.getHeader("user-agent");
logger.info("LoginAuthenticationSuecssHandler:当前登录的用户:{}"+authentication.getName());
String password = request.getParameter("password");
String token = JWTTest.getJwtBuilder(password, authentication.getName(), JWTTest.getKey());
logger.info("LoginAuthenticationSuecssHandler:加密后的token:{}"+token);
if (header.indexOf("Android") != -1) {
response.getWriter().write(objectMapper.writeValueAsString(ResponseMeaage.sucess(token,1, SysConstant.LOGIN_SUCCESS)));
}else if (header.indexOf("iPhone") != -1 || header.indexOf("iPad") != -1){
response.getWriter().write(objectMapper.writeValueAsString(ResponseMeaage.sucess(token,1, SysConstant.LOGIN_SUCCESS)));
}else{
response.getWriter().write(objectMapper.writeValueAsString(ResponseMeaage.sucess(token,1, SysConstant.LOGIN_SUCCESS)));
}
}
}
@Component
public class LoginAuthenticationFailHandler extends ExceptionMappingAuthenticationFailureHandler {
private Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
ObjectMapper objectMapper;
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
String header = request.getHeader("user-agent");
if (header.indexOf("Android") != -1) {
logger.info("onAuthenticationFailure:Phone Model:Android");
}else if (header.indexOf("iPhone") != -1 || header.indexOf("iPad") != -1){
logger.info("onAuthenticationFailure:Phone Model:iPhone");
}else{
logger.info("onAuthenticationFailure:Web{}"+header);
response.sendRedirect("http://localhost:9030/index.html");
}
logger.info("LoginAuthenticationFailHandler:当前用户登录失败{}"+request.getParameter("username"));
ResponseVo responseVo = ResponseMeaage.error("用户输入密码错误");
response.getWriter().write(objectMapper.writeValueAsString(responseVo));
}
}
@Component
public class AuthenticationTokenFilter extends BasicAuthenticationFilter {
private Logger logger = LoggerFactory.getLogger(getClass());
public AuthenticationTokenFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("BasicAuthenticationFilters");
String tokenHeader = request.getParameter("token");
System.out.println("tokenHeader:"+tokenHeader);
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Access-Control-Allow-Headers:x-requested-with,content-type");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
// 如果请求头中没有Authorization信息则直接放行了
if (StringUtils.isEmpty(tokenHeader)) {
chain.doFilter(request, response);
return;
}
try {
SecurityContextHolder.getContext().setAuthentication(getAuthentication(tokenHeader));
logger.info("LoginAuthenticationSuecssHandler:设置Token成功");
super.doFilterInternal(request, response, chain);
}catch (Exception e){
logger.info("当前token验证信息出错:token{}",tokenHeader);
}
chain.doFilter(request, response);
// 如果请求头中有token,则进行解析,并且设置认证信息
}
private UsernamePasswordAuthenticationToken getAuthentication(String token) {
//解析Token时将“Bearer ”前缀去掉
Claims jwtToken = JWTTest.cc(token, JWTTest.getKey());
String username = jwtToken.get("username").toString();
logger.info("getAuthentication:username{}",username);
if (!StringUtils.isEmpty(username)){
return new UsernamePasswordAuthenticationToken(username, null, null);
}
return null;
}
}
@Component
public class SpringUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
if (SpringUtils.applicationContext == null) {
SpringUtils.applicationContext = applicationContext;
}
}
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//根据name
public static Object getBean(String name) {
return getApplicationContext().getBean(name);
}
//根据类型
public static
public class JWTTest {
public static Key getKey(){
Key key = new SecretKeySpec("javastack".getBytes(),
SignatureAlgorithm.HS512.getJcaName());
return key;
}
public static String getJwtBuilder(String password,String user,Key key){
Map
文章标题:Springboot+Spring-Security+JWT Sso单点登录
文章链接:http://soscw.com/index.php/essay/59837.html