微人事第十天:登陆表单详细配置

对于登录接口,登录成功后的响应,登录失败后的响应,我们都可以在 WebSecurityConfigurerAdapter 的实现类中进行配置。例如下面这样
(以下内容是springboot项目配置好基础spring security以后的内容,spring security的基本配置这里就不重复了。)
下面来详细解释配置的代码:

以下定义了两个访问路径分别所需的权限,除了以admin和user开头的路径其他路径的当问不需要权限:

.antMatchers("/admin/**").hasRole("admin")
.antMatchers("user/**").hasAnyRole("admin","user")
.anyRequest().authenticated()

设置登陆接口,如果用postman测试需要这个接口:

.and()
.formLogin()
.loginProcessingUrl("/doLogin")  //登陆接口

当我们访问需要登陆的路径时会自动跳转到跳转到/login路径

.loginPage("/login")   //登陆页面

定义登陆时,用户名的key默认是username,这里改为uname
密码的key默认是password,这里改为passwd。

.usernameParameter("uname")
.passwordParameter("passwd")

我们可以在 successHandler 方法中,配置登录成功的回调,如果是前后端分离开发的话,登录成功后返回 JSON 即可

.successHandler(new AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp,
                                                        Authentication authentication) throws IOException, ServletException {
                    

设置数据格式为json类型

resp.setContentType("application/json;charset=utf-8");

这里配置登陆成功之后的状态码以及信息

PrintWriter out = resp.getWriter();
Map map = new HashMap<>();
map.put("status",200);
map.put("msg",authentication.getPrincipal());
out.write(new ObjectMapper().writeValueAsString(map));

登陆失败和成功的配置道理是一样的,只是多了登陆失败具体原因的判断:
如下针对登陆失败的不同原因进行具体解释(以便于我们及时查错)

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","登陆失败");
                        }

完整代码:

package org.javaboy.security.config;

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.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 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;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    //告诉系统不加密
    @Bean
    PasswordEncoder passwordEncoder() {
        return NoOpPasswordEncoder.getInstance();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("javaboy").password("123").roles("admin")
                .and()
                .withUser("江南一点雨").password("456").roles("user");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("user/**").hasAnyRole("admin","user")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginProcessingUrl("/doLogin")  //登陆接口
                .loginPage("/login")   //登陆页面
                .usernameParameter("uname")
                .passwordParameter("passwd")
                .successHandler(new AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp,
                                                        Authentication authentication) throws IOException, ServletException {
                        resp.setContentType("application/json;charset=utf-8");
                        PrintWriter out = resp.getWriter();
                        Map map = new HashMap<>();
                        map.put("status",200);
                        map.put("msg",authentication.getPrincipal());
                        out.write(new ObjectMapper().writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                .failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp,
                                                        AuthenticationException e) throws IOException, ServletException {
                        resp.setContentType("application/json;charset=utf-8");
                        PrintWriter out = resp.getWriter();
                        Map 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","登陆失败");
                        }
                        out.write(new ObjectMapper().writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                .permitAll()
                .and()
                .csrf().disable();
    }
}

接口编写相应的跳转页面:

package org.javaboy.security.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController  {

    @GetMapping("/hello")
    public String hello() {
        return "hello security";
    }

    @GetMapping("/admin/hello")
    public String admin() {
        return "hello admin!";
    }

    @GetMapping("/user/hello")
    public String user() {
        return "hello user!";
    }

    @GetMapping("/login")
    public String login() {
        return "please login!";
    }
}

启动项目,下面用postman进行测试:

先不登陆,随便访问一个需要登陆之后才能跳转的页面,看看spring security会不会自动帮我们跳转到登陆提示界面:

可以看到系统跳转到了/login接口,该接口返回的语句与postman中返回的语句相同,证明配置成功。
微人事第十天:登陆表单详细配置_第1张图片
微人事第十天:登陆表单详细配置_第2张图片

接下来,我们访问登陆接口进行登陆,注意这里登陆用户名和密码的key默认值都已经更改了:
登陆成功页面显示如下:
微人事第十天:登陆表单详细配置_第3张图片
登陆好之后我们再来访问之前路径:
可以看到访问的路径和上面的是一样的,但是结果不再是please login!了,访问成功。
微人事第十天:登陆表单详细配置_第4张图片

接下来我们删除cookies
微人事第十天:登陆表单详细配置_第5张图片
这次故意用错误的密码尝试登陆,看看会跳出什么提示信息:
微人事第十天:登陆表单详细配置_第6张图片

你可能感兴趣的:(微人事课程)