SpringBoot + Spring Security 前后端分离

SpringBoot + Spring Security 前后端分离(后端提供判断标识)

弄了一天:

  1. 主要是前后端分离前端接参 ,后台根据登录人所拥有的权限来给出可以访问的接口;
  2. 码云代码小demo,https://gitee.com/xueyuanxiang/codes/gzcy4r7219emtufh653ab43

引包

         <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>
		
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!-- mysql -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<!-- 工具类 -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.47</version>
		</dependency>
		<dependency>
		    <groupId>org.apache.tomcat.embed</groupId>
		    <artifactId>tomcat-embed-core</artifactId>
		</dependency>

Security 配置和登录逻辑

package com.kunyao.config;

import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;

import com.kunyao.interceptor.AjaxAccessDeniedHandler;
import com.kunyao.interceptor.AjaxAuthenticationEntryPoint;
import com.kunyao.interceptor.AjaxAuthenticationFailureHandler;
import com.kunyao.interceptor.AjaxAuthenticationSuccessHandler;
import com.kunyao.interceptor.MyLogoutSuccessHandle;
import com.kunyao.service.UserService;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

	@Autowired
	private UserService userService;
	@Autowired
	private AjaxAuthenticationEntryPoint authenticationEntryPoint;//未登录 返回给前端code 为:0
    @Autowired
    private AjaxAuthenticationSuccessHandler authenticationSuccessHandler;  // 登录成功返回给前端code 为:1
	@Autowired
	private AjaxAuthenticationFailureHandler authenticationFailureHandler;  //  登录失败返回给前端code 为:2
	@Autowired
	private AjaxAccessDeniedHandler accessDeniedHandler;    // 无权访问返回给前端code 为:3
	@Autowired
	private MyLogoutSuccessHandle logoutSuccessHandle;  //注销成功 给前端code 为:4
	
	@Bean
    public UserDetailsService userDetailsService() {
		
		  return username -> {
		        List<com.kunyao.entity.User> users = userService.getpassWord(username);
		        if (users == null || users.size() == 0) {
		            throw new UsernameNotFoundException("用户名未找到");
		        }
		        String password = users.get(0).getPassWord();
		        PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
		        String passwordAfterEncoder = passwordEncoder.encode(password);
		        Map<String,List<String>> dateMap = userService.getPermissionsByRoleId(users.get(0).getRoleId());
		        List<String> permissions = dateMap.get("permissions");//查出登录者所有拥有的权限	
		        String[] permissionArr = new String[permissions.size()];
		        int permissionArrIndex = 0;
		        for (String permission : permissions) {
		            permissionArr[permissionArrIndex] = permission;
		            permissionArrIndex++;
		        }
		        return User.withUsername(username).password(passwordAfterEncoder).authorities(permissionArr).build();
    };
}
	
	/**
	 * 注释中的拦截主要针对前后端分离
	 * 用这个HttpServletResponse里面的getWriter().write方法
	 * @return
	 */
	@Bean
	public WebSecurityConfigurerAdapter webSecurityConfigurerAdapter() {
	    return new WebSecurityConfigurerAdapter() {
	        @Override
	        public void configure(HttpSecurity httpSecurity) throws Exception {
	            httpSecurity.
                authorizeRequests().antMatchers("/test/**").permitAll().//test下的链接可以被任何人访问,不作验证拦截
                and().authorizeRequests().antMatchers("/admin/**").hasRole("admin").
                and().authorizeRequests().antMatchers("/manager/**").hasAuthority("admin").//admin下的链接需要admin权限的人才可以访问
                and().authorizeRequests().anyRequest().authenticated().// 其他 url 都需要身份认证
                and().httpBasic().authenticationEntryPoint(authenticationEntryPoint).//定义认证拦截
                and().exceptionHandling().accessDeniedHandler(accessDeniedHandler).//无权访问拦截
                
                and().formLogin().
                loginProcessingUrl("/security/login").//定义前端访问的接口(这里只是定义一个名字,项目是没有这个接口的,调用的还是Security自己登陆接口)
//	            loginPage("/test89/login1").//定义跳转的页面(前后端分离的话直接在下面拦截里给前端code)
//	            defaultSuccessUrl("/test89/login2").//定义成功跳转的接口
                failureHandler(authenticationFailureHandler).//定义失败拦截
                successHandler(authenticationSuccessHandler).//定义成功拦截
                usernameParameter("username").passwordParameter("password").//可以重新定义前端传过来的用户名密码接受字段
                
                and().logout().
                logoutSuccessHandler(logoutSuccessHandle).//定义注销拦截
//	            logoutUrl("/logout").//定义注销接口
//	            logoutSuccessUrl("/logoutSuccess").//定义注销成功跳转接口
                invalidateHttpSession(true).deleteCookies("cookiename").//成功注销后删除缓存中cookie
//              addLogoutHandler(new MyLogoutHandle()).//上面定义过了
//                and().cors().跨域的
                and().csrf().disable();
	        }
	    };
	}
}

拦截器且通过Security自己的登录接口返回标识给前端

没有权限

package com.yiyun.member.interceptor;


import com.alibaba.fastjson.JSON;
import com.yiyun.member.utils.JsonResult;

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;

//无权限
@Component
public class AjaxAccessDeniedHandler implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
    	JsonResult result = new JsonResult("3");
	    result.setFlag(false);
	    result.setMsg("Need Authorities!");
        httpServletResponse.getWriter().write(JSON.toJSONString(result));
    }
}

未登录

package com.yiyun.member.interceptor;

import com.alibaba.fastjson.JSON;
import com.yiyun.member.utils.JsonResult;

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;

@Component
public class AjaxAuthenticationEntryPoint implements AuthenticationEntryPoint {

	//未登录
    @Override
    public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
    	JsonResult result = new JsonResult("0");
	    result.setFlag(true);
	    result.setMsg("Need Authorities!");

        httpServletResponse.getWriter().write(JSON.toJSONString(result));
    }
}

登录失败

package com.yiyun.member.interceptor;
import com.alibaba.fastjson.JSON;
import com.yiyun.member.utils.JsonResult;

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;

@Component
public class AjaxAuthenticationFailureHandler implements AuthenticationFailureHandler {
//登录失败
    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
    	JsonResult result = new JsonResult("2");
	    result.setFlag(false);
	    result.setMsg("用户名或密码不正确!");
	    httpServletResponse.setContentType("application/json;charset=UTF-8");
        httpServletResponse.getWriter().write(JSON.toJSONString(result));
    }
}

登录成功

package com.yiyun.member.interceptor;
import com.alibaba.fastjson.JSON;
import com.yiyun.member.utils.JsonResult;

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;

@Component
public class AjaxAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

	//登录成功
    @Override 
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse   httpServletResponse, Authentication authentication) throws IOException, ServletException {
    	 JsonResult result = new JsonResult("1");
	    result.setFlag(true);
	    result.setMsg("Login Success!");

        httpServletResponse.getWriter().write(JSON.toJSONString(result));
    }
}

注销成功

package com.kunyao.interceptor;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.kunyao.utils.JsonResult;

@Component
public class MyLogoutSuccessHandle implements LogoutSuccessHandler {
	//注销成功
    @Override
    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
    	JsonResult result = new JsonResult();
    	result.setCode("4");
	    result.setFlag(true);
	    result.setMessage("LoginOut Success!");
        httpServletResponse.getWriter().write(JSON.toJSONString(result));
    }
}

返回给前端封装类

package com.kunyao.utils;

import java.io.Serializable;

public class JsonResult implements Serializable{
	
	private static final long serialVersionUID = 1L;
	private String code;
	
	private String message;
	
	private Object data;
	
	private Boolean flag;

	
	public String getCode() {
		
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}

	public Boolean getFlag() {
		return flag;
	}

	public void setFlag(Boolean flag) {
		this.flag = flag;
	}
}

查询登录人权限

package com.kunyao.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.kunyao.dao.PolePermissionDao;
import com.kunyao.dao.UserDao;
import com.kunyao.entity.PolePermission;
import com.kunyao.entity.User;


@Service
@Transactional
public class UserService {

	@Autowired
	private UserDao userDao;
	
	@Autowired
	private PolePermissionDao polePermissionDao;

	public List<User> getpassWord(String userName) {
		List<User> user = userDao.findByUserName(userName);
		return user;
	}

	public Map<String, List<String>> getPermissionsByRoleId(Integer roleId) {
		Map<String,List<String>> resultMap = new HashMap<String, List<String>>();
		List<PolePermission> polePermissionList =  polePermissionDao.findByRoleId(roleId);
		List<String> permissions = new ArrayList<String>();
	    for(int i =0 ;i<polePermissionList.size();i++) {
	    	permissions.add(polePermissionList.get(i).getPermission());
	    }
	    resultMap.put("permissions", permissions);
		return resultMap;
	}

	
}

数据库建表
直接在项目里面拉出来的用户表
会员和角色 一对多的关系
会员的等级对应这不同的权限一对多关系
demo项目结构
项目结构

demo是根据这两个帖子 来做的https://blog.csdn.net/larger5/article/details/81047869

https://www.cnblogs.com/LOVE0612/p/9897647.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值