前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot入门建站全系列(十一)Spring-security进行权限认证

SpringBoot入门建站全系列(十一)Spring-security进行权限认证

原创
作者头像
品茗IT
修改2019-08-13 10:58:38
3990
修改2019-08-13 10:58:38
举报
文章被收录于专栏:品茗IT品茗IT

SpringBoot入门建站全系列(十一)Spring-security进行权限认证

Spring 是一个非常流行和成功的 Java 应用开发框架。Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。

Spring-security其实就是用filter,多请求的路径进行过滤。

如果是基于Session,那么Spring-security会对cookie里的sessionid进行解析,找到服务器存储的sesion信息,然后判断当前用户是否符合请求的要求。

如果是token,则是解析出token,然后将当前请求加入到Spring-security管理的权限信息中去。

一、配置

本文假设你已经引入spring-boot-starter-web。已经是个SpringBoot项目了,如果不会搭建,可以打开这篇文章看一看《SpringBoot入门建站全系列(一)项目建立》

1.1 Maven依赖
代码语言:txt
复制
<dependency>
	<groupId>org.mybatis.spring.boot</groupId>
	<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
	<groupId>mysql</groupId>
	<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
	<groupId>org.apache.commons</groupId>
	<artifactId>commons-dbcp2</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
</dependency>

Spring-security一般需要从数据库中查询用户信息的,所以这里还是要把mybatis引入,以查询用户信息使用。

1.2 配置文件

application.properties 中需要添加下面的配置:

代码语言:txt
复制
spring.datasource.type=org.apache.commons.dbcp2.BasicDataSource
spring.datasource.dbcp2.max-wait-millis=60000
spring.datasource.dbcp2.min-idle=20
spring.datasource.dbcp2.initial-size=2
spring.datasource.dbcp2.validation-query=SELECT 1
spring.datasource.dbcp2.connection-properties=characterEncoding=utf8
spring.datasource.dbcp2.validation-query=SELECT 1
spring.datasource.dbcp2.test-while-idle=true
spring.datasource.dbcp2.test-on-borrow=true
spring.datasource.dbcp2.test-on-return=false

spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/boot?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
spring.datasource.username=cff
spring.datasource.password=123456

mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

这里的配置主要就是数据库连接和数据源、mybatis的配置。因为要连接数据库。

二、安全控制核心

Spring Security的核心配置就是继承WebSecurityConfigurerAdapter并注解@EnableWebSecurity的配置。

这个配置指明了用户名密码的处理方式、请求路径的开合、登录登出控制等和安全相关的配置。

ApiSecurityConfig:

代码语言:txt
复制
package com.cff.springbootwork.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.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

import com.cff.springbootwork.security.handler.AjaxAuthFailHandler;
import com.cff.springbootwork.security.handler.AjaxAuthSuccessHandler;
import com.cff.springbootwork.security.handler.AjaxLogoutSuccessHandler;
import com.cff.springbootwork.security.handler.UnauthorizedEntryPoint;
import com.cff.springbootwork.security.provider.SimpleAuthenticationProvider;

@EnableWebSecurity
public class ApiSecurityConfig {

	@Configuration                                                   
	public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
		@Autowired
		private SimpleAuthenticationProvider simpleAuthenticationProvider;
		
		@Autowired
		public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
			auth.authenticationProvider(simpleAuthenticationProvider);
		}

		@Override
		public void configure(HttpSecurity http) throws Exception {
			http.csrf().disable().exceptionHandling()
					.authenticationEntryPoint(new UnauthorizedEntryPoint())
					.and().headers()
					.frameOptions().disable().and().authorizeRequests()
					.antMatchers("/login").permitAll()
					.antMatchers("/login.html").permitAll()
					.antMatchers("/error.html").permitAll()
					.antMatchers("/img/**").permitAll()
					.antMatchers("/css/**").permitAll()
					.antMatchers("/pub/**").permitAll()
					.anyRequest().authenticated()
					.and()
					.formLogin()
					.usernameParameter("userName").passwordParameter("password")
					.loginProcessingUrl("/login")
					.successHandler(new AjaxAuthSuccessHandler())
					.failureHandler(new AjaxAuthFailHandler())
					.and()
					.logout()
					.logoutUrl("/logout").logoutSuccessHandler(new AjaxLogoutSuccessHandler());
		}
	}
}

这里:

  • SimpleAuthenticationProvider :用户名密码校验过程的处理方式。
  • UnauthorizedEntryPoint:未授权的统一处理方式。
  • successHandler、failureHandler、logoutSuccessHandler顾名思义,就是响应处理逻辑,如果不打算单独处理,只做跳转,有响应的successForwardUrl、failureForwardUrl、logoutSuccessUrl等。

三、用户名密码校验

SimpleAuthenticationProvider实现了AuthenticationProvider 接口的authenticate方法,提供用户名密码的校验,校验成功后,生成UsernamePasswordAuthenticationToken。

SimpleAuthenticationProvider:

代码语言:txt
复制
package com.cff.springbootwork.security.provider;

import java.util.Collection;

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.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.stereotype.Component;

import com.cff.springbootwork.mybatis.domain.UserInfo;
import com.cff.springbootwork.mybatis.service.UserInfoService;

@Component
public class SimpleAuthenticationProvider implements AuthenticationProvider {
	@Autowired
	private UserInfoService userInfoService;

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {

		String userName = authentication.getPrincipal().toString();
		UserInfo user = userInfoService.getUserInfoByUserName(userName);

		if (user == null) {
			throw new BadCredentialsException("查无此用户");
		}
		if (user.getPasswd() != null && user.getPasswd().equals(authentication.getCredentials())) {
			Collection<? extends GrantedAuthority> authorities = AuthorityUtils.NO_AUTHORITIES;

			return new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPasswd(), authorities);
		} else {
			throw new BadCredentialsException("用户名或密码错误。");
		}
	}

	@Override
	public boolean supports(Class<?> arg0) {
		return true;
	}

}

四、安全处理的一些handler

UnauthorizedEntryPoint:

代码语言:txt
复制
package com.cff.springbootwork.security.handler;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;

import com.cff.springbootwork.security.model.ResultCode;
import com.cff.springbootwork.security.model.ResultModel;
import com.fasterxml.jackson.databind.ObjectMapper;

public class UnauthorizedEntryPoint implements AuthenticationEntryPoint {
	@Override
	public void commence(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException authException) throws IOException, ServletException {
		ResultModel rm = new ResultModel(ResultCode.CODE_40004);
		ObjectMapper mapper = new ObjectMapper();
		response.setStatus(HttpStatus.OK.value());
		response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
		mapper.writeValue(response.getWriter(), rm);
	}
}

AjaxAuthSuccessHandler:

代码语言:txt
复制
package com.cff.springbootwork.security.handler;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;

import com.cff.springbootwork.security.model.ResultCode;
import com.cff.springbootwork.security.model.ResultModel;
import com.fasterxml.jackson.databind.ObjectMapper;

public class AjaxAuthSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
	protected final Log logger = LogFactory.getLog(this.getClass());

	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication authentication) throws IOException, ServletException {
		ResultModel rm = new ResultModel(ResultCode.CODE_00000);
		ObjectMapper mapper = new ObjectMapper();
		response.setStatus(HttpStatus.OK.value());
		response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
		mapper.writeValue(response.getWriter(), rm);
	}

}

AjaxAuthFailHandler:

代码语言:txt
复制
package com.cff.springbootwork.security.handler;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;

import com.cff.springbootwork.security.model.ResultCode;
import com.cff.springbootwork.security.model.ResultModel;
import com.fasterxml.jackson.databind.ObjectMapper;

public class AjaxAuthFailHandler extends SimpleUrlAuthenticationFailureHandler {
	@Override
	public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException exception) throws IOException, ServletException {
		ResultModel rm = new ResultModel(ResultCode.CODE_00014.getCode(), exception.getMessage());
		ObjectMapper mapper = new ObjectMapper();
		response.setStatus(HttpStatus.OK.value());
		response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
		mapper.writeValue(response.getWriter(), rm);
	}

}

AjaxLogoutSuccessHandler:

代码语言:txt
复制
package com.cff.springbootwork.security.handler;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;

import com.cff.springbootwork.security.model.ResultCode;
import com.cff.springbootwork.security.model.ResultModel;
import com.fasterxml.jackson.databind.ObjectMapper;

public class AjaxLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
	public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
			throws IOException, ServletException {
		ResultModel rm = new ResultModel(ResultCode.CODE_00000);
		ObjectMapper mapper = new ObjectMapper();
		response.setStatus(HttpStatus.OK.value());
		response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
		mapper.writeValue(response.getWriter(), rm);

	}

}

五、用户信息查询

UserInfoService:

代码语言:txt
复制
package com.cff.springbootwork.mybatis.service;

import java.util.List;

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

import com.cff.springbootwork.mybatis.dao.UserInfoDao;
import com.cff.springbootwork.mybatis.domain.UserInfo;

@Service
public class UserInfoService {
	@Autowired
	UserInfoDao userInfoDao;
	public UserInfo getUserInfoByUserName(String userName){
		return userInfoDao.findByUserName(userName);
	}
}

UserInfoDao:

代码语言:txt
复制
package com.cff.springbootwork.mybatis.dao;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;

import com.cff.springbootwork.mybatis.domain.UserInfo;

@Mapper
public interface UserInfoDao {
	@Select({
		"<script>",
	        "SELECT ",
	        "user_name as userName,passwd,name,mobile,valid, user_type as userType",
	        "FROM user_info",
	        "WHERE user_name = #{userName,jdbcType=VARCHAR}",
	   "</script>"})
	UserInfo findByUserName(@Param("userName") String userName);
	
	
}

六、过程中用到的实体

详细完整的实体,可以访问品茗IT-博客《SpringBoot入门建站全系列(十一)Spring-security进行权限认证》进行查看

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • SpringBoot入门建站全系列(十一)Spring-security进行权限认证
    • 一、配置
      • 1.1 Maven依赖
        • 1.2 配置文件
          • 二、安全控制核心
            • 三、用户名密码校验
              • 四、安全处理的一些handler
                • 五、用户信息查询
                  • 六、过程中用到的实体
                    相关产品与服务
                    网站建设
                    网站建设(Website Design Service,WDS),是帮助您快速搭建企业网站的服务。通过自助模板建站工具及专业设计服务,无需了解代码技术,即可自由拖拽模块,可视化完成网站管理。全功能管理后台操作方便,一次更新,数据多端同步,省时省心。使用网站建设服务,您无需维持技术和设计师团队,即可快速实现网站上线,达到企业数字化转型的目的。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档