我们知道企业级权限框架一般有Shiro,Shiro虽然强大,但是却不属于Spring成员之一,接下来我们说说SpringSecurity这款强大的安全框架。费话不多说,直接上干货。

pom文件引入以下依赖:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

首先创建WebConfig继承WebSecurityConfigurerAdapter,实现代码如下:


import com.zaxxer.hikari.HikariDataSource;
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.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.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
import org.springframework.session.data.redis.RedisOperationsSessionRepository; /**
* author:yuxuan
* date:2018/12/16/016 12:00
* description
*/
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebConfig extends WebSecurityConfigurerAdapter { @Autowired
private MyAuthenticationSuccessHandler myAuthenticationSuccess;
@Autowired
private MyAuthenticationProvider myAuthenticationProvider;
@Autowired
private MyAuthenticationFailHandler myAuthenticationFailHandler;
@Autowired
private MyUserDetailService myUserDetailService;
@Autowired
private HikariDataSource dataSource; @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(myAuthenticationProvider);
} @Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().sameOrigin();
http.csrf()
.disable()
.authorizeRequests()
.antMatchers("/static/**","/resources/**","/login/userauth").permitAll()
.antMatchers("/health","/autoconfig","/configprops","/beans","/dump","/env","/env/**","/info","/mappings","/metrics","/metrics/**","/shutdown","/trace").hasRole("SYS")
.anyRequest().authenticated()
.and().formLogin().loginPage("/login")
.successHandler(myAuthenticationSuccess)
.failureHandler(myAuthenticationFailHandler)
.permitAll()
.and()
.logout().deleteCookies("SESSION", "remember-me")
.and().sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true).expiredUrl("/login").and()
.and().rememberMe().alwaysRemember(true).tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(60 * 60 * 24 * 7) //设置记住我的时间为7天
.userDetailsService(myUserDetailService)//设置userDetailsService
;
http.headers().cacheControl(); //禁用缓存
} @Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers( "/api/**", "/resources/**", "/static/**", "/public/**", "/webui/**", "/h2-console/**"
, "/configuration/**", "/swagger-resources/**", "/api-docs", "/api-docs/**", "/v2/api-docs/**"
, "/**/*.css", "/**/*.js","/**/*.ftl", "/**/*.png ", "/**/*.jpg", "/**/*.gif ", "/**/*.svg", "/**/*.ico", "/**/*.ttf", "/**/*.woff");
} @Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl tokenRepository = new JdbcTokenRepositoryImpl();
tokenRepository.setDataSource(dataSource);
return tokenRepository;
}
}

以上为SpringSecurity的主要配置类,包括登录,退出,拦截那些url等。

MyAuthenticationProvinder类,主要实现认证


import lombok.extern.log4j.Log4j;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
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.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component; import java.util.Collection; @Log4j2
@Component
public class MyAuthenticationProvider implements AuthenticationProvider { @Autowired
private MyUserDetailService myUserDetailService; @Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException { String userName = authentication.getName();// 这个获取表单输入中的用户名
String password = (String) authentication.getCredentials();
log.info("登陸用戶:"+userName);
UserInfo userInfo = (UserInfo) myUserDetailService.loadUserByUsername(userName); String pwd = MD5Utils.encryptMD5Pwd(password,userInfo.getSalt());
System.out.println(pwd);
if(!pwd.equals(userInfo.getPassword())){
throw new UsernameNotFoundException("用户名或者密码不正确");
} Collection<? extends GrantedAuthority> authorities = userInfo.getAuthorities(); return new UsernamePasswordAuthenticationToken(userInfo, pwd, authorities); } @Override
public boolean supports(Class<?> aClass) {
return true;
}
}

创建类MyUserDetailService实现UserDetailService


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 java.util.Date; @Component
public class MyUserDetailService implements UserDetailsService { @Autowired
private UserRepo userRepo; @Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { //UserInfo userInfo = new UserInfo(1,"張三","abc","sdf",1);
User user = userRepo.findFirstByAccount(s);
if(user ==null){
user = userRepo.findFirstByMobile(s);
if(user == null){
throw new UsernameNotFoundException("用户名或者密码不正确");
}
}
//保存最后一次登录日志
user.setLastLoginTime(new Date());
userRepo.save(user);
UserInfo userInfo = new UserInfo(
user.getId(),
user.getPassword(),
user.getSalt(),
user.getStatus(),
return userInfo;
}
}

创建类 MyAuthenticationSuccessHandler 继承 AuthenticationSuccessHandler 此类主要是SpringSecurity登录成功后的处理逻辑


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 MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler{
@Override
public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
httpServletResponse.sendRedirect("/index");
}
}

创建类 MyAuthenticationFailHandler继承 AuthenticationFailHandler 此类主要是SpringSecurity登录失败后的处理逻辑


import lombok.extern.log4j.Log4j2;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
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; @Log4j2
@Component
public class MyAuthenticationFailHandler implements AuthenticationFailureHandler { @Override
public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
log.info(e.getMessage());
httpServletRequest.setAttribute("msg","");
if(e instanceof UsernameNotFoundException){
httpServletRequest.setAttribute("msg","用戶名或者密碼錯誤");
}
httpServletRequest.getRequestDispatcher("/login").forward(httpServletRequest,httpServletResponse); }
}

以上为主要配置,启动项目,访问/login会要求输入用户名密码。

SpringBoot2.0整合SpringSecurity实现自定义表单登录的更多相关文章

  1. SpringSecurity 自定义表单登录

    SpringSecurity 自定义表单登录 本篇主要讲解 在SpringSecurity中 如何 自定义表单登录 , SpringSecurity默认提供了一个表单登录,但是实际项目里肯定无法使用的 ...

  2. SpringBoot集成Spring Security(4)——自定义表单登录

    通过前面三篇文章,你应该大致了解了 Spring Security 的流程.你应该发现了,真正的 login 请求是由 Spring Security 帮我们处理的,那么我们如何实现自定义表单登录呢, ...

  3. spring security 之自定义表单登录源码跟踪

    ​ 上一节我们跟踪了security的默认登录页的源码,可以参考这里:https://www.cnblogs.com/process-h/p/15522267.html 这节我们来看看如何自定义单表认 ...

  4. springboot2.0整合springsecurity前后端分离进行自定义权限控制

    在阅读本文之前可以先看看springsecurity的基本执行流程,下面我展示一些核心配置文件,后面给出完整的整合代码到git上面,有兴趣的小伙伴可以下载进行研究 使用maven工程构建项目,首先需要 ...

  5. SpringBoot2.0 整合 SpringSecurity 框架,实现用户权限安全管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.Security简介 1.基础概念 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方 ...

  6. SpringBoot2.0整合SpringSecurity实现WEB JWT认证

    相信很多做技术的朋友都做过前后端分离项目,项目分离后认证就靠JWT,费话不多说,直接上干活(写的不好还请多多见谅,大牛请绕行) 直接上代码,项目为Maven项目,结构如图: 包分类如下: com.ap ...

  7. activiti自定义流程之整合(三):整合自定义表单创建模型

    本来在创建了表单之后应该是表单列表和预览功能,但是我看了看整合的代码,和之前没有用angularjs的基本没有什么变化,一些极小的变动也只是基于angularjs的语法,因此完全可以参考之前说些的表单 ...

  8. activiti自定义流程之整合(四):整合自定义表单部署流程定义

    综合前几篇博文内容,我想在整合这一部分中应该会有很多模块会跳过不讲,就如自定义表单的表单列表那一块,因为这些模块在整合的过程中都几乎没有什么改动,再多讲也是重复无用功. 正因为如此,在创建了流程模型之 ...

  9. Winform自定义表单(转)

    出处:http://www.newlifex.com/showtopic-167.aspx 好吧,附件真的损坏了,原始代码我也没有了,再提取我也没精力了,不好意思,哪位之前下过可以重发一遍吗?不过即使 ...

随机推荐

  1. <MyBatis>入门八 工作原理

    1.获取sqlSessionFactory对象 首先拿到全局配置文件的流对象 创建SqlSessionFactoryBuilder对象,并调用build方法,把流传进去 build方法 创建一个XML ...

  2. 数据分布vs聚类-数据预处理技巧-对数变换

    对于原始数据分布倾斜 利用统计或数学变换来减轻数据分布倾斜的影响.使原本密集的区间的值尽可能的分散, 原本分散的区间的值尽量的聚合. Log变换通常用来创建单调的数据变换.它的主要作用在于帮助稳定方差 ...

  3. radial profiles of mean streamwise velocity at X/D=3

    matlab code: load aver_ux_array.dat; load z_array.dat; r=z_array(:,); r=r.' r_j=0.00125; r_nor=r/d; ...

  4. js获取昨天,最近7天,最近30天通用方法

    function formatDate (val) { // 格式化时间 let start = new Date(val) let y = start.getFullYear() let m = ( ...

  5. intel compiler的表现

    好久没弄这个东西,今天突然想试下,代码没写完,以后补. #include <stdio.h> #include <stdlib.h> #include <time.h&g ...

  6. 3.2.2.5 BRE运算符优先级

        在数学表达式里,正则表达式的运算符具有某种已定义的优先级,指的是某个运算符(优先级较高)将比其他运算符先被处理.       BRE运算符优先级,由高至低   运算符 表示含义 [..] [= ...

  7. 3.8.5 多重选择:switch语句

        在处理多个选项时,使用if/else结构显得有些笨拙.               Scanner in = new Scanner(System.in);             Syste ...

  8. Crackme3 破解教程

    Crackme3 破解教程 1.先用PEiD对 Crackme3进行 壳测试 点击File右边的按钮,选中Crackme3 结果如下图所示: 即 无壳. 试运行软件 点击 Register now! ...

  9. enum 的使用

    public enum Color { RED(), GREEN(), BLANK(), YELLO(); // 成员变量 private String name; private int index ...

  10. 【Codeforces 1096D】Easy Problem

    [链接] 我是链接,点我呀:) [题意] 让你将一个字符串删掉一些字符. 使得字符串中不包含子序列"hard" 删掉每个字符的代价已知为ai 让你求出代价最小的方法. [题解] 设 ...