Spring Security (two) memory-based authentication

Spring Security + Shiro + OAuth2 in a project which
github Address: https://github.com/ZiCheng-Web/springboot-security

First, the memory-based authentication

Create a class and inherits WebSecurityConfigurerAdapter this method, and the like configure the override method 3,
wherein the process parameter comprises 3 to HttpSecurity (HTTP request safe handling),
AuthenticationManagerBuilder (authentication manager generator) and WebSecurity (WEB Safety).

You can use a custom configuration class certification MyWebSecurityConfig inherited from WebSecurityConfigurerAdapter , to customize the configuration of SpringSecurity.

package com.zicheng.config;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.*;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * 子诚
 * Description:
 * 时间:2020/3/5 17:34
 */

/**
 * 创建一个类并继承WebSecurityConfigurerAdapter这个方法,并在之类中重写configure的3个方法,
 * 其中3个方法中参数包括为HttpSecurity(HTTP请求安全处理),
 * AuthenticationManagerBuilder(身份验证管理生成器)
 * WebSecurity(WEB安全)。
 */
@Configuration
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    PasswordEncoder passwordEncoder() {
        //不对密码进行加密
        return NoOpPasswordEncoder.getInstance();
    }

    //AuthenticationManagerBuilder(身份验证管理生成器)
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("root").password("123").roles("ADMIN", "DBA")
                .and()
                //配置了用户为admin,密码为123,角色为admin和user
                .withUser("admin").password("123").roles("ADMIN", "USER")
                .and()
                .withUser("wang").password("123").roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //antMatchers:单词意思,反匹配
                //访问“/admin/** ”模式的 URL 必须具备 ADMIN 的角色
                .antMatchers("/admin/**").hasRole("ADMIN")
                //访问 “ /user/**”模式的 URL 必须具备 ADMIN 或者 USER 的角色
                .antMatchers("/user/**").access("hasAnyRole('ADMIN','USER')")
                //访问
                .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
                //除了上面的URL模式之外,,用户访问其他的 URL 都必须认证后访问(登录后访问)
                .anyRequest().authenticated()
                .and()
                //表示和登录相关的接口都不需要认证即可访问。
                .formLogin()
                //跳转到登陆页面/login_page,访问URL依旧是/login
                .loginPage("/login_page")
                .loginProcessingUrl("/login")
                //用户名参数为name,密码参数为passwd
                .usernameParameter("name").passwordParameter("passwd")
                //登陆成功处理器
                .successHandler(new AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest req,
                                                        HttpServletResponse resp,
                                                        Authentication auth)
                            throws IOException {
                        //auth:用来获取当前用户的信息,比如会返回用户的角色
                        Object principal = auth.getPrincipal();
                        //以JSON的形式返回至前端
                        resp.setContentType("application/json;charset=utf-8");
                        PrintWriter out = resp.getWriter();
                        resp.setStatus(200);
                        Map<String, Object> map = new HashMap<>();
                        map.put("status", 200);
                        map.put("msg", principal);
                        ObjectMapper om = new ObjectMapper();
                        out.write(om.writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
//                .successForwardUrl("/hello")
                .failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest req,
                                                        HttpServletResponse resp,
                                                        AuthenticationException e)
                        //AuthenticationException e,通过这个异常参数可以获取登录失败的原因,进而给用户一个明确的提示
                            throws IOException {
                        resp.setContentType("application/json;charset=utf-8");
                        PrintWriter out = resp.getWriter();
                        resp.setStatus(401);
                        Map<String, Object> map = new HashMap<>();
                        map.put("status", 401);
                        if (e instanceof LockedException) {
                            map.put("msg", "账户被锁定,登录失败!");
                        } else if (e instanceof BadCredentialsException) {
                            map.put("msg", "账户名或密码输入错误,登录失败!");
                        } else if (e instanceof DisabledException) {
                            map.put("msg", "账户被禁用,登录失败!");
                        } else if (e instanceof AccountExpiredException) {
                            map.put("msg", "账户已过期,登录失败!");
                        } else if (e instanceof CredentialsExpiredException) {
                            map.put("msg", "密码已过期,登录失败!");
                        } else {
                            map.put("msg", "登录失败!");
                        }
                        ObjectMapper om = new ObjectMapper();
                        out.write(om.writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                }).permitAll()
                .and()
                //注销退出功能
                .logout()
                .logoutUrl("/logout")
                .clearAuthentication(true)//清除用户信息
                .invalidateHttpSession(true)//清除用户的session
                .addLogoutHandler(new LogoutHandler() {
                    @Override
                    public void logout(HttpServletRequest req,
                                       HttpServletResponse resp,
                                       Authentication auth) {

                    }
                })
                .logoutSuccessHandler(new LogoutSuccessHandler() {
                    @Override
                    public void onLogoutSuccess(HttpServletRequest req,
                                                HttpServletResponse resp,
                                                Authentication auth)
                            throws IOException {
                        resp.sendRedirect("/login_page");
                    }
                })
                .and()
                //csrf:跨站请求伪造:攻击者构造网站后台某个功能接口的请求地址,诱导用户去点击或者用特殊方法让该请求地址自动加载。
                //关闭CSRF
                .csrf().disable();
    }
}


If there is no login page, put .loginPage ( "/ login_page") commented, cancellation processor inside the / login_page, read / login

Test controller

@RestController
public class HelloController {
        //简单测试一下
        @GetMapping("/hello")
        public String hello(){
            return "hello SpringSecurity";
        }
        @GetMapping("admin/hello")
        public String admin(){
            return "hello admin";
        }
        @GetMapping("user/hello")
        public String user(){
            return "hello user";
        }
        @GetMapping("db/hello")
        public String dba(){
            return "hello dba";
        }
}

Login Success:
Here Insert Picture Description
failure of the landing
Here Insert Picture Description
write-off will be returned directly to the login page.

Published 44 original articles · won praise 5 · Views 894

Guess you like

Origin blog.csdn.net/qq_40634246/article/details/104679486