登录功能

添加一个配置类

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
UserDetailsService userDetailsService; @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(password());
} @Bean
PasswordEncoder password() {
return new BCryptPasswordEncoder();
} @Override
protected void configure(HttpSecurity http) throws Exception { http.formLogin() // 表单登录
.and().authorizeRequests()
.anyRequest()//其他请求
.authenticated();//需要认证 //关闭csrf
http.csrf().disable();
}
}

登录的实现类

/**
* SpringSecurity 自动调用该类
* 登录实现类 默认 继承 UserDetailsService
*/
@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {
@Resource
private AdminMapper adminMapper; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
QueryWrapper<Admin> wrapper = new QueryWrapper<>();
wrapper.eq("username", username);
Admin admin = adminMapper.selectOne(wrapper);
if (admin == null) {
throw new UsernameNotFoundException("用户名不存在");
}
List<GrantedAuthority> auths = new ArrayList<>();
return new User(admin.getUsername(), new BCryptPasswordEncoder().encode(admin.getPassword()), auths);
}
}

自定义登录页面

只需要修改一下配置类

	@Override
protected void configure(HttpSecurity http) throws Exception { http.formLogin() // 表单登录
.loginPage("/login") //配置登录页面 引入了thymeleaf
.loginProcessingUrl("/user/login")//设置哪个是登录的url
.permitAll()
.and().authorizeRequests()
.anyRequest()//其他请求
.authenticated();//需要认证 //关闭csrf
http.csrf().disable();
}

自定义认证成功或失败状态码

如果你想要在认证成功或者失败后拿到你自己定义的状态码,那你可以参考以下步骤

主要是下面的两个处理器

/**
* 用户认证失败处理类
*/
@Component("userLoginAuthenticationFailureHandler")
public class UserLoginAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { @Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
System.out.println("===" + exception.getMessage());
JsonData jsonData = null;
jsonData = new JsonData(403,"用户名或密码错误"); String json = new Gson().toJson(jsonData);//包装成Json 发送的前台
System.out.println(json);
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter(); out.write(json);
out.flush();
out.close();
}
}
/**
* 用户认证成功处理类
*/
@Component("userLoginAuthenticationSuccessHandler")
public class UserLoginAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler { @Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
JsonData jsonData = new JsonData(200,"认证OK");
String json = new Gson().toJson(jsonData);
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter(); out.write(json);
out.flush();
out.close();
}
}

在配置类中添加自己写的两个处理类

注入自己写的两个处理器

    @Resource
private UserLoginAuthenticationFailureHandler userLoginAuthenticationFailureHandler;//验证失败的处理类 @Resource
private UserLoginAuthenticationSuccessHandler userLoginAuthenticationSuccessHandler;//验证成功的处理类

配置上两个处理类

@Override
protected void configure(HttpSecurity http) throws Exception { http.formLogin() // 表单登录
.loginPage("/login") //配置登录页面 引入了thymeleaf
.loginProcessingUrl("/user/login")//设置哪个是登录的url
.failureHandler(userLoginAuthenticationFailureHandler)//验证失败处理
.successHandler(userLoginAuthenticationSuccessHandler)//验证成功处理
.permitAll()
.and().authorizeRequests()
.anyRequest()//其他请求
.authenticated();//需要认证 //关闭csrf
http.csrf().disable();
}

此时的登录页面

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登录</title> </head>
<body>
<section>
<span>用户名:<input type="text" id="username" name="username"/> <br/> </span>
<span>用户密码:<input type="password" id="password" name="password"/> <br/> </span>
<button onclick="login()">登录</button>
</section> <script type="text/javascript" src="../static/js/jquery.js" th:src="@{/js/jquery.js}"></script>
<script>
function login(){
let username = document.getElementById("username");
let password = document.getElementById("password"); let username_and_password = {
username:username.value,
password:password.value
}
$.ajax({
type:"Post",
url:"/user/login",
data:username_and_password,
success:function (data) {
console.log(data)
console.log(data.code)
console.log(data.msg)
if (data.code == 200){ //拿到自己定义的状态码进行跳转
alert(data.msg)
// window.location.href = "/hello";
// console.log("hehe")
}else if (data.code == 403){
alert(data.msg)
} else {
alert("客户端出错")
}
}
})
} </script>
</body>
</html>

写一个注解

标注该注解的方法或类,直接放行。

/**
* 声明不用拦截的接口
**/
@Target({ElementType.TYPE, ElementType.METHOD}) //该注解可以用在类上或者方法上
@Retention(RetentionPolicy.RUNTIME)
public @interface NoAuthentication {
}

配置类中主要是以下这个方法

//设置哪些不需要认证
@Override
public void configure(WebSecurity web) throws Exception {
//静态资源放行,我就随便写写,根据自己静态资源结构去写。
String[] urls = new String[]{
"/js/**",
"/imgs/**",
"/css/**"
};
ApplicationContext applicationContext = ApplicationContextHelper.getApplicationContext();
List<String> whiteList = new ArrayList<>();
for (String url : urls) {
whiteList.add(url);
} RequestMappingHandlerMapping requestMappingHandlerMapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
// 获取url与类和方法的对应信息
Map<RequestMappingInfo, HandlerMethod> map = requestMappingHandlerMapping.getHandlerMethods();
for (Map.Entry<RequestMappingInfo, HandlerMethod> requestMappingInfoHandlerMethodEntry : map.entrySet()) {
RequestMappingInfo key = requestMappingInfoHandlerMethodEntry.getKey();
HandlerMethod value = requestMappingInfoHandlerMethodEntry.getValue();
Set<String> patterns = key.getPatternsCondition().getPatterns();
//无需权限都可以访问的类型
NoAuthentication noAuthentication = value.getBeanType().getAnnotation(NoAuthentication.class);
if (null != noAuthentication) {//整个controller不需要权限访问的
RequestMapping annotation = value.getBeanType().getAnnotation(RequestMapping.class);
if (null != annotation) {
String path = annotation.value()[0];
String suffix = "**";
if (path.lastIndexOf("/") != path.length() - 1)
suffix = "/**";
String s = path + suffix;
if (!whiteList.contains(s)) {
whiteList.add(s);
}
}
} else {//方法不需要权限访问的
NoAuthentication annotation = value.getMethod().getAnnotation(NoAuthentication.class);
if (null != annotation) {
patterns.forEach(p -> {
if (!whiteList.contains(p)) {
whiteList.add(p);
}
});
}
}
}
System.out.println("-----");
for (String s : whiteList) {
System.out.println(s);
}
urls = whiteList.toArray(urls);
super.configure(web);
web.httpFirewall(defaultHttpFirewall()); web.ignoring().antMatchers(urls);
}
/**
* 允许出现双斜杠的URL
*
* @return
*/
@Bean
public HttpFirewall defaultHttpFirewall() {
return new DefaultHttpFirewall();
}

测试:把注解放在某个方法或者某个类上面,可以发现不用登陆也能直接进行接口的访问

作用:如果你有一些接口是不需要认证的,比如说你去淘宝逛东西,你只是看看的话,要是让你登陆的话就有些不合理了,这时你就可以在类似需求的类上加上该注解,就能实现不用登陆也能访问。

欢迎

源码:https://github.com/zhi-ac/security_demo

如果觉得有收获,不妨花个几秒钟点个赞,欢迎关注我的公众号玩编程地码农,目前在写数据结构与算法、计算机基础、java相关的知识。

SpringSecurity自定义注解和处理器的更多相关文章

  1. java自定义注解学习(注解处理器)

    如果没有用来读取注解的方法和工作,那么注解也就不会比注释更有用处了.使用注解的过程中,很重要的一部分就是创建于使用注解处理器.Java SE5扩展了反射机制的API,以帮助程序员快速的构造自定义注解处 ...

  2. java自定义注解实现前后台参数校验

    2016.07.26 qq:992591601,欢迎交流 首先介绍些基本概念: Annotations(also known as metadata)provide a formalized way ...

  3. 深入理解Java:注解(Annotation)自定义注解入门

    转载:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 元注解: 元注解的作用就是负责注解其他注解.Java5.0定义了4个标准 ...

  4. 【转】深入理解Java:注解(Annotation)自定义注解入门

    http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 元注解: 元注解的作用就是负责注解其他注解.Java5.0定义了4个标准的me ...

  5. java自定义注解注解方法、类、属性等等【转】

    http://anole1982.iteye.com/blog/1450421 http://www.open-open.com/doc/view/51fe76de67214563b20b385320 ...

  6. Java注解(Annotation)自定义注解入门

    要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的注解之前,我们就必须要了解Java为我们提供的元注解和相关定义注解的语法. 元注解: 元注解的作用就是负责注解其他注解.Java5. ...

  7. Java注解(自定义注解、view注入)

    注解这东西虽然在jdk1.5就加进来了,但他的存在还是因为使用Afinal框架的view注入才知道的.一直觉得注入特神奇,加了一句就可以把对应view生成了. 下面我们来认识一下注解这个东西 一.注解 ...

  8. Java:注解(Annotation)自定义注解入门

    转载地址:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 要深入学习注解,我们就必须能定义自己的注解,并使用注解,在定义自己的 ...

  9. 注解(Annotation)自定义注解入门

    摘自:http://www.cnblogs.com/peida/archive/2013/04/24/3036689.html 元注解: 元注解的作用就是负责注解其他注解.Java5.0定义了4个标准 ...

随机推荐

  1. [atAGC027D]Modulo Matrix

    对网格图黑白染色,在黑色格中填不同的质数,白色格中填相邻黑色格的lcm+1,但这样会超过1e15的上限将网格图划分为两类对角线,每一条对角线选一个质数,然后每一个点就是两条对角线的质数相乘,而白格的值 ...

  2. [cf1392I]Kevin and Grid

    令$v$为点数(有公共点的格子中存在红/蓝色).$e$为边数(有公共边的格子中存在红/蓝色).$f$为以此法(即仅考虑这些点和边)所分割出的区域数(包括外面).$s$为连通块个数,将欧拉定理简单扩展, ...

  3. [NOI2021] 量子通信

    嗯. NOI2021最白给的一题. PS:很后悔没打同步赛,少了一张同步赛Ag 考虑加黑的256位01串,我们思考一下. 因为\(k\)小于16,所以我们直接分成16块.所以一定可以的绝对有一块是完全 ...

  4. python版的MCScan绘图

    最近发现了python版的MCScan,是个大宝藏.由于走了不少弯路,终于画出美图,赶紧记录下来. github地址 https://github.com/tanghaibao/jcvi/wiki/M ...

  5. 【豆科基因组】大豆适应性位点GWAS分析 [转载]

    目录 材料与方法 结果分析 本文利用99085个高质量SNP 通过STRUCTURE,PCA和neighbour-joining tree的群体结构分析将地方品种分为三个亚群,这些亚群表现出地理上的遗 ...

  6. 除了GO基因本体论,还有PO、TO、CO等各种Ontology?

    目录 PO/TO CO 后记 我们最常用最熟悉的功能数据库之一:GO(gene onotology),基因本体论.其实是一套标准词汇术语,目的是从不同角度来描述某个基因的特点和功能,三大本体如生物学进 ...

  7. Pycharm的简单配置和使用

    外观 Ctrl+滚轮改变字体大小:file -> Setting ->Editor-〉General -> Mouse: 字体.颜色:file->settings->Ed ...

  8. Linux-centos7设置静态IP地址

    参考:https://blog.csdn.net/sjhuangx/article/details/79618865

  9. 『与善仁』Appium基础 — 16、APPium基础操作API

    目录 1.前置代码 2.安装和卸载APP 3.判断APP是否已安装 4.关闭APP软件和关闭驱动对象 5.发送文件到手机和获取手机中的文件 6.获取当前屏幕内元素结构(重点) 7.脚本内启动其他APP ...

  10. 【模板】有源汇有上下界最大流(网络流)/ZOJ3229

    先导知识 无源汇有上下界可行流 题目链接 https://vjudge.net/problem/ZOJ-3229 https://www.luogu.com.cn/problem/P5192 (有改动 ...