SpringBoot +SpringSecurity+mysql 实现用户数据权限管理

符号 阅读:676 2021-03-31 17:20:08 评论:0

通用用户数据权限sql建库 和初始化脚本:

/* 
 Navicat MySQL Data Transfer 
 
 Source Server         : 192.168.1.73 
 Source Server Type    : MySQL 
 Source Server Version : 80015 
 Source Host           : 192.168.1.73:3306 
 Source Schema         : boot-security 
 
 Target Server Type    : MySQL 
 Target Server Version : 80015 
 File Encoding         : 65001 
 
 Date: 15/07/2019 16:40:44 
*/ 
 
SET NAMES utf8mb4; 
SET FOREIGN_KEY_CHECKS = 0; 
 
-- ---------------------------- 
-- Table structure for u_permission 
-- ---------------------------- 
DROP TABLE IF EXISTS `u_permission`; 
CREATE TABLE `u_permission`  ( 
  `id` bigint(20) NOT NULL AUTO_INCREMENT, 
  `url` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'url地址', 
  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'url描述', 
  PRIMARY KEY (`id`) USING BTREE 
) ENGINE = InnoDB AUTO_INCREMENT = 21 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; 
 
-- ---------------------------- 
-- Records of u_permission 
-- ---------------------------- 
INSERT INTO `u_permission` VALUES (1, 'userInfo/userList', '用户管理'); 
INSERT INTO `u_permission` VALUES (2, 'userInfo/userAdd', '用户添加'); 
INSERT INTO `u_permission` VALUES (3, 'userInfo/userDel', '用户删除'); 
 
-- ---------------------------- 
-- Table structure for u_role 
-- ---------------------------- 
DROP TABLE IF EXISTS `u_role`; 
CREATE TABLE `u_role`  ( 
  `id` bigint(20) NOT NULL AUTO_INCREMENT, 
  `name` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '角色名称', 
  `type` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '角色类型', 
  PRIMARY KEY (`id`) USING BTREE 
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; 
 
-- ---------------------------- 
-- Records of u_role 
-- ---------------------------- 
INSERT INTO `u_role` VALUES (1, 'admin', '1'); 
INSERT INTO `u_role` VALUES (2, 'user', '2'); 
 
-- ---------------------------- 
-- Table structure for u_role_permission 
-- ---------------------------- 
DROP TABLE IF EXISTS `u_role_permission`; 
CREATE TABLE `u_role_permission`  ( 
  `rid` bigint(20) NULL DEFAULT NULL COMMENT '角色ID', 
  `pid` bigint(20) NULL DEFAULT NULL COMMENT '权限ID', 
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', 
  PRIMARY KEY (`id`) USING BTREE 
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; 
 
-- ---------------------------- 
-- Records of u_role_permission 
-- ---------------------------- 
INSERT INTO `u_role_permission` VALUES (1, 1, 1); 
INSERT INTO `u_role_permission` VALUES (1, 2, 2); 
INSERT INTO `u_role_permission` VALUES (1, 3, 3); 
INSERT INTO `u_role_permission` VALUES (2, 1, 4); 
INSERT INTO `u_role_permission` VALUES (2, 2, 5); 
INSERT INTO `u_role_permission` VALUES (2, 3, 6); 
 
-- ---------------------------- 
-- Table structure for u_user 
-- ---------------------------- 
DROP TABLE IF EXISTS `u_user`; 
CREATE TABLE `u_user`  ( 
  `id` bigint(20) NOT NULL AUTO_INCREMENT, 
  `nickname` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户昵称', 
  `email` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '邮箱|登录帐号', 
  `pswd` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '密码', 
  `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', 
  `last_login_time` datetime(0) NULL DEFAULT NULL COMMENT '最后登录时间', 
  `status` bigint(1) NULL DEFAULT 1 COMMENT '1:有效,0:禁止登录', 
  PRIMARY KEY (`id`) USING BTREE 
) ENGINE = InnoDB AUTO_INCREMENT = 15 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; 
 
-- ---------------------------- 
-- Records of u_user 
-- ---------------------------- 
INSERT INTO `u_user` VALUES (1, 'admin', 'admin@163.com', 'C4CA4238A0B923820DCC509A6F75849B', '2019-04-27 22:44:44', NULL, 1); 
 
-- ---------------------------- 
-- Table structure for u_user_role 
-- ---------------------------- 
DROP TABLE IF EXISTS `u_user_role`; 
CREATE TABLE `u_user_role`  ( 
  `uid` bigint(20) NULL DEFAULT NULL COMMENT '用户ID', 
  `rid` bigint(20) NULL DEFAULT NULL COMMENT '角色ID', 
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键', 
  PRIMARY KEY (`id`) USING BTREE 
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic; 
 
-- ---------------------------- 
-- Records of u_user_role 
-- ---------------------------- 
INSERT INTO `u_user_role` VALUES (1, 2, 1); 
 
SET FOREIGN_KEY_CHECKS = 1; 

项目截图:

1、springsecurity 配置类:SecurityConfiguration

只要使用spring security都要有这样一个配置类(如果是类配置的话),继承WebSecurityConfigurerAdapter 主要实现两个方法configure(AuthenticationManagerBuilder auth)和 configure(HttpSecurity http)

AuthenticationManagerBuilder: 主要配置身份认证来源,也就是用户及其角色。

HttpSecurity 主要配置路径:也就是资源的访问权限(是否需要认证,需要什么角色等)。

自定义securityConfiguration:SpringSecurityConfig

package com.zzg.security.config; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 
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.builders.WebSecurity; 
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 
import org.springframework.security.web.authentication.AuthenticationFailureHandler; 
import org.springframework.security.web.authentication.AuthenticationSuccessHandler; 
 
import com.zzg.security.provider.SpringSecurityProvider; 
 
/** 
 * spring-security 配置文件 
 * @author zzg 
 * 
 */ 
 
@Configuration 
@EnableWebSecurity //开启Spring Security的功能 
@EnableGlobalMethodSecurity(prePostEnabled=true)//开启注解控制权限 
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { 
	 
	 /** 
     * עSpringSecurityProvider 
     */ 
    @Autowired 
    private SpringSecurityProvider provider; 
     
    /** 
     *AuthenticationSuccessHandler 
     */ 
    @Autowired 
    private AuthenticationSuccessHandler securityAuthenticationSuccessHandler; 
    /** 
     *  AuthenticationFailureHandler 
     */ 
    @Autowired 
    private AuthenticationFailureHandler securityAuthenticationFailHandler; 
 
    /** 
	 * 定义需要过滤的静态资源(等价于HttpSecurity的permitAll) 
	 */ 
	@Override 
	public void configure(WebSecurity webSecurity) throws Exception { 
		webSecurity.ignoring().antMatchers("static/css/**"); 
	} 
 
	@Override 
	protected void configure(HttpSecurity http) throws Exception { 
		// TODO Auto-generated method stub 
		http.authorizeRequests() 
        .antMatchers("/login").permitAll() // 不需要权限路径 
        .anyRequest().authenticated()       
        .and() 
        .formLogin() 
        .loginPage("/login")    // 登入页面 
        .successHandler(securityAuthenticationSuccessHandler)  //自定义成功处理器 
        .failureHandler(securityAuthenticationFailHandler)     //自定义失败处理器 
        .permitAll() 
        .and() 
        .logout(); 
		 
	} 
 
 
 
	@Override 
	protected void configure(AuthenticationManagerBuilder builder) throws Exception { 
		// 自定义身份验证提供者 
		builder.authenticationProvider(provider); 
	} 
	 
	 
	 
 
} 

2、springsecurity 认证接口:AuthenticationProvider

spring security实现自定义认证,需要实现AuthenticationProvider接口:主要实现方法authenticate(Authentication authentication)

自定义AuthenticationProvider:SpringSecurityProvider

package com.zzg.security.provider; 
 
import org.apache.commons.codec.digest.DigestUtils; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.security.authentication.AuthenticationProvider; 
import org.springframework.security.authentication.BadCredentialsException; 
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 
import org.springframework.security.core.Authentication; 
import org.springframework.security.core.AuthenticationException; 
import org.springframework.security.core.userdetails.UsernameNotFoundException; 
import org.springframework.stereotype.Component; 
import com.zzg.security.userservice.AuthUserDetails; 
import com.zzg.security.userservice.CustomUserService; 
 
/** 
 *自定义身份验证提供者 
 *  
 * @author zzg 
 * 
 */ 
@Component 
public class SpringSecurityProvider implements AuthenticationProvider { 
 
	@Autowired 
	private CustomUserService userDetailService; 
 
	@Override 
	public Authentication authenticate(Authentication authentication) throws AuthenticationException { 
		// TODO Auto-generated method stub 
		String userName = authentication.getName(); 
		String password = (String) authentication.getCredentials(); 
 
	    // 查询用户权限信息 
		AuthUserDetails userInfo = (AuthUserDetails) userDetailService.loadUserByUsername(userName);  
		if (userInfo == null) { 
			throw new UsernameNotFoundException(""); 
		} 
 
		// 密码判断 
		String encodePwd = DigestUtils.md5Hex(password).toUpperCase(); 
		if (!userInfo.getPassword().equals(encodePwd)) { 
			throw new BadCredentialsException(""); 
		} 
 
		return new UsernamePasswordAuthenticationToken(userInfo, userInfo.getPassword(), 
				userInfo.getAuthorities()); 
	} 
 
	@Override 
	public boolean supports(Class<?> authentication) { 
		// TODO Auto-generated method stub 
		return UsernamePasswordAuthenticationToken.class.equals(authentication); 
	} 
 
} 

2、springsecurity 用户详情信息接口:UserDetailsService

spring security实现自定义用户详情信息,需要实现UserDetailsService接口:主要实现方法loadUserByUsername(String username)

自定义UserDetailsService:CustomUserService

package com.zzg.security.userservice; 
 
import java.util.List; 
import java.util.stream.Collectors; 
 
import org.springframework.beans.factory.annotation.Autowired; 
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.Component; 
 
import com.zzg.entity.Permission; 
import com.zzg.entity.Role; 
import com.zzg.entity.RolePermission; 
import com.zzg.entity.User; 
import com.zzg.entity.UserRole; 
import com.zzg.service.PermissionService; 
import com.zzg.service.RolePermissionService; 
import com.zzg.service.RoleService; 
import com.zzg.service.UserRoleService; 
import com.zzg.service.UserService; 
/** 
 * 自定义用户查询服务 
 * @author zzg 
 * 
 */ 
 
@Component 
public class CustomUserService implements UserDetailsService { 
	@Autowired 
	private UserService userService; 
	@Autowired 
	private UserRoleService userRoleService; 
	@Autowired 
	private RoleService roleService; 
	@Autowired 
	private RolePermissionService rolePermissionService; 
	@Autowired 
	private PermissionService permissionService; 
	 
 
	@Override 
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
		// TODO Auto-generated method stub 
		User user = userService.findByUserName(username); 
		if(user == null){ 
			 throw new UsernameNotFoundException(""); 
		} 
		List<UserRole> list = userRoleService.findByUid(user.getId()); 
		List<Long> rIds = list.stream().map(UserRole::getRid).collect(Collectors.toList()); 
		 
		List<Role> roles = roleService.findByIds(rIds); 
		List<Long> roleIds = roles.stream().map(Role::getId).collect(Collectors.toList()); 
		 
		List<RolePermission> rolePermissions = rolePermissionService.findByRids(roleIds); 
		List<Long> pIds = rolePermissions.stream().map(RolePermission::getPid).collect(Collectors.toList()); 
		 
		List<Permission> permissions = permissionService.findByIds(pIds); 
		 
		AuthUserDetails authUserDetails = new AuthUserDetails(user.getNickname(),user.getPswd(),roles,permissions); 
		 
		return authUserDetails; 
	} 
 
} 

3、springsecurity 用户信息拓展:UserDetails

spring security 拓展用户信息,继承UserDetails类,主要方法:Collection<? extends GrantedAuthority> getAuthorities() 构建用户权限信息。

自定义UserDetails:AuthUserDetails

package com.zzg.security.userservice; 
 
import java.util.ArrayList; 
import java.util.Collection; 
import java.util.Collections; 
import java.util.List; 
 
import org.springframework.security.core.GrantedAuthority; 
import org.springframework.security.core.authority.SimpleGrantedAuthority; 
import org.springframework.security.core.userdetails.UserDetails; 
 
import com.zzg.entity.Permission; 
import com.zzg.entity.Role; 
 
@SuppressWarnings("serial") 
public class AuthUserDetails implements UserDetails { 
	 
	private String nickname; 
 
    private String pswd; 
     
    
    private List<Role> roles; 
   
    private List<Permission> permission; 
     
   
	public String getNickname() { 
		return nickname; 
	} 
 
	public void setNickname(String nickname) { 
		this.nickname = nickname; 
	} 
 
	public String getPswd() { 
		return pswd; 
	} 
 
	public void setPswd(String pswd) { 
		this.pswd = pswd; 
	} 
 
	public List<Role> getRoles() { 
		return roles; 
	} 
 
	public void setRoles(List<Role> roles) { 
		this.roles = roles; 
	} 
 
	public List<Permission> getPermission() { 
		return permission; 
	} 
 
	public void setPermission(List<Permission> permission) { 
		this.permission = permission; 
	} 
	 
	 
	public AuthUserDetails(String nickname, String pswd, List<Role> roles, List<Permission> permission) { 
		super(); 
		this.nickname = nickname; 
		this.pswd = pswd; 
		this.roles = roles; 
		this.permission = permission; 
	} 
	 
	public AuthUserDetails(){ 
		this.nickname = "NA"; 
		this.pswd = "NA"; 
		this.roles = Collections.EMPTY_LIST; 
		this.permission = Collections.EMPTY_LIST; 
	} 
 
	@Override 
	public Collection<? extends GrantedAuthority> getAuthorities() { 
		// 基于用户角色名称构建权限信息 
		 List<GrantedAuthority> auths = new ArrayList<>(); 
		 List<Role> roles = this.getRoles(); 
		 for (Role role : roles) { 
	            auths.add(new SimpleGrantedAuthority(role.getName())); 
	        } 
		  
		return auths; 
	} 
 
	/** 
	 * 
	 */ 
	@Override 
	public String getPassword() { 
		// TODO Auto-generated method stub 
		return this.pswd; 
	} 
 
	/** 
	 *  
	 */ 
	@Override 
	public String getUsername() { 
		// TODO Auto-generated method stub 
		return this.nickname; 
	} 
  
	/** 
	 *  
	 */ 
	@Override 
	public boolean isAccountNonExpired() { 
		// TODO Auto-generated method stub 
		return true; 
	} 
 
	/** 
	 *  
	 */ 
	@Override 
	public boolean isAccountNonLocked() { 
		// TODO Auto-generated method stub 
		return true; 
	} 
 
	/** 
	 *  
	 */ 
	@Override 
	public boolean isCredentialsNonExpired() { 
		// TODO Auto-generated method stub 
		return true; 
	} 
 
	/** 
	 *  
	 */ 
	@Override 
	public boolean isEnabled() { 
		// TODO Auto-generated method stub 
		return true; 
	} 
 
} 

4、自定义springsecurity 登入成功处理的Handler:一般需要实现AuthenticationSuccessHandler 接口,覆写onAuthenticationSuccess(HttpServletRequest request,HttpServletResponse response, Authentication authentication) throws IOException, ServletException 方法

自定义AuthenticationSuccessHandler:SecurityAuthenticationSuccessHandler

package com.zzg.security.handler; 
 
import java.io.IOException; 
 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.security.core.Authentication; 
import org.springframework.security.web.DefaultRedirectStrategy; 
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; 
import org.springframework.stereotype.Component; 
 
import com.zzg.redis.util.RedisUtil; 
 
/** 
 * 用户登入成功 
 * @author zzg 
 * 
 */ 
@Component("securityAuthenticationSuccessHandler") 
public class SecurityAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { 
	@Autowired 
	private RedisUtil redisUtil; 
 
	@Override 
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, 
			Authentication authentication) throws ServletException, IOException { 
		// 用户登入成功,补充相关业务逻辑 
         new DefaultRedirectStrategy().sendRedirect(request, response, "/defaults"); 
	} 
 
	 
} 

5、自定义springsecurity 登入失败处理的Handler:一般需要实现AuthenticationFailureHandler接口,覆写onAuthenticationFailure(HttpServletRequest request,HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException 方法

package com.zzg.security.handler; 
 
import java.io.IOException; 
import java.net.URLEncoder; 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import org.springframework.security.core.AuthenticationException; 
import org.springframework.security.web.DefaultRedirectStrategy; 
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; 
import org.springframework.stereotype.Component; 
 
/** 
 * 用户登入失败 
 * @author zzg 
 * 
 */ 
@Component("securityAuthenticationFailHandler") 
public class SecurityAuthenticationFailHandler extends SimpleUrlAuthenticationFailureHandler { 
	 
	@Override 
	public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, 
			AuthenticationException exception) throws IOException, ServletException { 
        String redirectUrl = "/login?message=" + URLEncoder.encode(exception.getMessage(),"UTF-8"); 
        new DefaultRedirectStrategy().sendRedirect(request, response, redirectUrl); 
	} 
     
     
} 

6、自定义权限不足处理器,实现AccessDeniedHandler接口,覆写handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) 方法

package com.zzg.security.access.denied; 
 
import java.io.IOException; 
import java.io.PrintWriter; 
 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
import org.springframework.security.access.AccessDeniedException; 
import org.springframework.security.web.DefaultRedirectStrategy; 
import org.springframework.security.web.access.AccessDeniedHandler; 
import org.springframework.stereotype.Component; 
 
import com.zzg.security.util.HttpUtils; 
/** 
 * 自定义权限不足处理器 
 * @author zzg 
 * 
 */ 
@Component 
public class SpringSecurityAccessDeniedHandler implements AccessDeniedHandler { 
 
	@Override 
	public void handle(HttpServletRequest request, HttpServletResponse response, 
			AccessDeniedException accessDeniedException) throws IOException, ServletException { 
		// TODO Auto-generated method stub 
		boolean isAjax = HttpUtils.isAjaxRequest(request); 
		if(isAjax){ 
			// 前端提示授权信息不足 
			response.setContentType("text/html;charset=UTF-8"); 
			PrintWriter out = response.getWriter(); 
			out.println("权限不足"); 
			 
		} else { 
			// 后端直接跳转至权限的错误页面 
			new DefaultRedirectStrategy().sendRedirect(request, response, "/errors"); 
		} 
		 
	} 
	 
 
} 

至此已经完成基于数据库存储的Spring Security权限控制的核心配置。

以下的代码主要是controller、springmvc 配置和工具类代码代码:

Http 工具类:

package com.zzg.security.util; 
 
import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.nio.charset.Charset; 
 
import javax.servlet.ServletRequest; 
import javax.servlet.http.HttpServletRequest; 
 
import org.springframework.http.HttpHeaders; 
 
public class HttpUtils { 
	/** 
	 * 获取请求Body 
	 * 
	 * @param request 
	 * @return 
	 */ 
	public static String getBodyString(ServletRequest request) { 
		StringBuilder sb = new StringBuilder(); 
		InputStream inputStream = null; 
		BufferedReader reader = null; 
		try { 
			inputStream = request.getInputStream(); 
			reader = new BufferedReader(new InputStreamReader(inputStream, Charset.forName("UTF-8"))); 
			String line = ""; 
			while ((line = reader.readLine()) != null) { 
				sb.append(line); 
			} 
		} catch (IOException e) { 
			e.printStackTrace(); 
		} finally { 
			if (inputStream != null) { 
				try { 
					inputStream.close(); 
				} catch (IOException e) { 
					e.printStackTrace(); 
				} 
			} 
			if (reader != null) { 
				try { 
					reader.close(); 
				} catch (IOException e) { 
					e.printStackTrace(); 
				} 
			} 
		} 
		return sb.toString(); 
	} 
 
	/** 
	 * 从request获取登录的IP 
	 */ 
	public static String getIpAddress(HttpServletRequest request) { 
		String ip = request.getHeader("x-forwarded-for"); 
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
			ip = request.getHeader("Proxy-Client-IP"); 
		} 
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
			ip = request.getHeader("WL-Proxy-Client-IP"); 
		} 
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
			ip = request.getHeader("HTTP_CLIENT_IP"); 
		} 
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
			ip = request.getHeader("HTTP_X_FORWARDED_FOR"); 
		} 
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
			ip = request.getHeader("X-Real-IP"); 
		} 
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 
			ip = request.getRemoteAddr(); 
		} 
		return ip; 
	} 
 
	/** 
	 * 判断是否为ajax请求 
	 */ 
	public static boolean isAjaxRequest(HttpServletRequest request) { 
		if (request.getHeader(HttpHeaders.ACCEPT) != null 
				&& request.getHeader(HttpHeaders.ACCEPT).indexOf("application/json") > -1 
				|| (request.getHeader("X-Requested-With") != null 
						&& request.getHeader("X-Requested-With").equalsIgnoreCase("XMLHttpRequest"))) { 
			return true; 
		} 
		return false; 
	} 
} 

springMVC 配置:

package com.zzg.springmvc.config; 
 
import org.springframework.context.annotation.Configuration; 
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 
 
/** 
 * 访问路径配置类 可以理解成做简单访问过滤的,转发到相应的视图页面 
 *  
 * @author Veiking 
 */ 
@Configuration 
public class SpringMvcConfig implements WebMvcConfigurer { 
 
	@Override 
	public void addViewControllers(ViewControllerRegistry registry) { 
		// TODO Auto-generated method stub 
		registry.addViewController("/login").setViewName("login.html"); 
		registry.addViewController("/").setViewName("index.html"); 
		registry.addViewController("/index").setViewName("index.html"); 
	} 
 
	@Override 
	public void addResourceHandlers(ResourceHandlerRegistry registry) { 
		// TODO Auto-generated method stub 
		registry.addResourceHandler("/**").addResourceLocations("classpath:/static/**"); 
	} 
	 
	 
 
} 
package com.zzg.controller; 
 
import org.springframework.security.access.prepost.PreAuthorize; 
import org.springframework.stereotype.Controller; 
import org.springframework.ui.Model; 
import org.springframework.web.bind.annotation.RequestMapping; 
 
@Controller 
public class LoginController { 
	 
	/** 
	 * 鉴权用户是否拥有指定权限 
	 * @param model 
	 * @param tt 
	 * @return 
	 */ 
	@RequestMapping("/admin") 
	@PreAuthorize("hasAuthority('admin')") 
	public String admin(Model model, String tt) { 
		return "admin"; 
	} 
	 
	@RequestMapping("/hello") 
	public String hello(Model model, String tt) { 
		return "hello"; 
	} 
	/** 
	 * 登入成功跳转页面 
	 * @param model 
	 * @param tt 
	 * @return 
	 */ 
	@RequestMapping("/defaults") 
	public String defaults(Model model, String tt) { 
		return "defaults"; 
	} 
	 
	/** 
	 * 权限不足跳转页面 
	 * @param model 
	 * @param tt 
	 * @return 
	 */ 
	@RequestMapping("/errors") 
	public String errors(Model model, String tt) { 
		return "errors"; 
	} 
	 
	 
	 
 
} 

静态页面:

admin.html

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml" 
	xmlns:th="http://www.thymeleaf.org" 
	xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"> 
<head> 
<title>ADMIN</title> 
<link rel="stylesheet" th:href="@{static/css/bootstrap.min.css}"/> 
<style type="text/css"> 
body { padding: 40px; } 
</style> 
</head> 
<body> 
	<h1>ADMIN</h1> 
	<br/>你好:<a sec:authentication="name"></a> 
	<p> 
		<a th:href="@{/index}"> INDEX</a> 
		<a th:href="@{/admin}"> | ADMIN</a> 
		<a th:href="@{/hello}"> | HELLO</a> 
		<br/><hr/> 
        <form th:action="@{/logout}" method="post"> 
            <input type="submit" class="btn btn-primary" value="注销"/> 
        </form> 
	</p> 
</body> 
</html>

defaults.html

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml" 
	xmlns:th="http://www.thymeleaf.org" 
	xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"> 
<head> 
<title>成功默认登入页面</title> 
<link rel="stylesheet" th:href="@{static/css/bootstrap.min.css}"/> 
<style type="text/css"> 
body { padding: 40px; } 
</style> 
</head> 
<body> 
	<h1>成功默认登入页面</h1> 
	<br/>成功默认登入页面:<a sec:authentication="name"></a> 
	<p> 
		<a th:href="@{/index}"> INDEX</a> 
		<a th:href="@{/admin}"> | ADMIN</a> 
		<a th:href="@{/hello}"> | HELLO</a> 
		<br/><hr/> 
        <form th:action="@{/logout}" method="post"> 
            <input type="submit" class="btn btn-primary" value="注销"/> 
        </form> 
	</p> 
</body> 
</html>

error.html

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml" 
	xmlns:th="http://www.thymeleaf.org" 
	xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"> 
<head> 
<title>方法权限不足提示页面</title> 
<link rel="stylesheet" th:href="@{static/css/bootstrap.min.css}"/> 
<style type="text/css"> 
body { padding: 40px; } 
</style> 
</head> 
<body> 
	<h1>方法权限不足提示页面</h1> 
	<br/>方法权限不足提示页面:<a sec:authentication="name"></a> 
	<p> 
		<a th:href="@{/index}"> INDEX</a> 
		<a th:href="@{/admin}"> | ADMIN</a> 
		<a th:href="@{/hello}"> | HELLO</a> 
		<br/><hr/> 
        <form th:action="@{/logout}" method="post"> 
            <input type="submit" class="btn btn-primary" value="注销"/> 
        </form> 
	</p> 
</body> 
</html>

hello.html

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"	 
	xmlns:th="http://www.thymeleaf.org" 
	xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"> 
<head> 
<meta content="text/html;charset=UTF-8"/> 
<title>HELLO</title> 
<link rel="stylesheet" th:href="@{static/css/bootstrap.min.css}"/> 
<style type="text/css"> 
body { padding: 40px; } 
</style> 
</head> 
<body> 
	<h1>HELLO</h1> 
	<br/>你好:<a sec:authentication="name"></a> 
	<p> 
		<a sec:authorize="hasAuthority('admin')" th:href="@{/index}"> INDEX</a> 
		<a sec:authorize="hasAuthority('admin')" th:href="@{/admin}"> | ADMIN</a> 
		<a sec:authorize="hasAuthority('admin')" th:href="@{/hello}"> | HELLO</a> 
		<br/><hr/> 
        <form th:action="@{/logout}" method="post" sec:authorize="hasAuthority('admin')"> 
            <input type="submit" class="btn btn-primary" value="注销"/> 
        </form> 
	</p> 
</body> 
</html>

index.html

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml" 
	xmlns:th="http://www.thymeleaf.org" 
	xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"> 
<head> 
<title>主页</title> 
<link rel="stylesheet" th:href="@{static/css/bootstrap.min.css}"/> 
<style type="text/css"> 
body { padding: 40px; } 
</style> 
</head> 
<body> 
	<h1>INDEX</h1> 
	<br/>你好:<a sec:authentication="name"></a> 
	<p> 
		<a sec:authorize="hasAuthority('user')" th:href="@{/index}"> INDEX</a> 
		<a sec:authorize="hasAuthority('admin')" th:href="@{/admin}"> | ADMIN</a> 
		<a sec:authorize="hasAuthority('user')" th:href="@{/hello}"> | HELLO</a> 
		<br/><hr/> 
        <form th:action="@{/logout}" method="post"> 
            <input type="submit" class="btn btn-primary" value="注销"/> 
        </form> 
	</p> 
</body> 
</html>

login.html

<!DOCTYPE html> 
<html xmlns:th="http://www.thymeleaf.org"> 
<head> 
<meta content="text/html;charset=UTF-8"/> 
<title>登录</title> 
<link rel="stylesheet" th:href="@{static/css/bootstrap.min.css}"/> 
<style type="text/css"> 
body { padding: 20px; } 
.starter-template { width:350px; padding: 0 40px; text-align: center; } 
</style> 
</head> 
<body> 
	<p> 
		<a th:href="@{/index}"> INDEX</a> 
		<a th:href="@{/admin}"> | ADMIN</a> 
		<a th:href="@{/hello}"> | HELLO</a> 
		<br/> 
	</p> 
	<hr/> 
    <div class="starter-template"> 
     <p th:if="${param.logout}" class="bg-warning">已成功注销</p><!-- 1 --> 
	<p th:if="${param.error}" class="bg-danger">有错误,请重试</p> <!-- 2 --> 
	<h2>使用用户名密码登录</h2> 
	<form name="form"  th:action="@{/login}" action="/login" method="POST"> <!-- 3 --> 
		<div class="form-group"> 
			<label for="username">账号</label> 
			<input type="text" class="form-control" name="username" value="" placeholder="账号" /> 
		</div> 
		<div class="form-group"> 
			<label for="password">密码</label> 
			<input type="password" class="form-control" name="password" placeholder="密码" /> 
		</div> 
		<div class="form-group"> 
			<input type="submit" id="login" value="登录" class="btn btn-primary" /> 
		</div> 
 
	</form> 
    </div> 
</body> 
</html>

源码下载地址:待补充

标签:Spring Boot
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号