修改自定义安全配置CustSecurityConfig
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/index.html","/login.html","/login","/404.html").permitAll() // 给url配置角色访问权限 .antMatchers("/access/user").hasRole("USER") .antMatchers("/access/read").hasRole("READ") .antMatchers("/access/admin").hasRole("ADMIN") .anyRequest().authenticated() .and() .formLogin() // 指定使用自定义的登录界面 .loginPage("/login.html") .loginProcessingUrl("/login") .failureUrl("/404.html") // 指定跳转的错误页面 .and() .csrf().disable(); } 复制代码
重新启动应用,使用错误的用户名密码登录
基于AJAX登录
在登录页面增加ajax代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>登陆</title> <style> //此处省略了样式代码,样式没有任何改变 </style> <script type="text/javascript" src="/js/jquery-3.4.1.js"></script> <script type="text/javascript"> $(function(){ //juqery的入口函数 $("#btnLogin").click(function(){ var uname = $("#username").val(); var pwd = $("#password").val(); $.ajax({ url:"/login", type:"POST", data:{ "username":uname, "password":pwd }, dataType:"json", success:function(resp){ alert(resp.msg) } }) }) }) </script> </head> <body> <div class="main-body"> <div class="login-main"> <div class="login-top"> <span>Login</span> <span class="bg1"></span> <span class="bg2"></span> </div> <form class="layui-form login-bottom"> <div class="center"> <div class="item"> <span class="icon icon-2"></span> <input type="text" id="username" lay-verify="required" placeholder="请输入登录账号" maxlength="24"/> </div> <div class="item"> <span class="icon icon-3"></span> <input type="password" id="password" lay-verify="required" placeholder="请输入密码" maxlength="20"> <span class="bind-password icon icon-4"></span> </div> <div class="layui-form-item" style="text-align:center; width:100%;height:100%;margin:0px;"> <button class="login-btn" lay-submit="" lay-filter="login" id="btnLogin">立即登录</button> </div> </div> </form> </div> </div> </body> </html> 复制代码
取消了form表单提交数据,增加了ajax代码,并给username和password以及登录按钮增加了id属性,通过ajax代码获取属性的value,向后端发送 POST请求 新增handler包,增加successHandler即校验用户名密码成功后后执行的handler,及faliureHandler校验密码失败后执行的handler,增加@Component属性,将这两个Handler交割Spring管理
@Component public class CustSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { // 登录的用户信息验证成功后执行的方法 response.setContentType("text/json;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.println("{"msg":"登录成功"}"); writer.flush(); writer.close(); } } 复制代码
@Component public class CustFailureHandler implements AuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { // 验证登录信息失败后执行的方法 response.setContentType("text/json;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.println("{"msg":"验证失败"}"); writer.flush(); writer.close(); } } 复制代码
修改自定义安全配置
@Configuration @EnableWebSecurity public class CustSecurityConfig extends WebSecurityConfigurerAdapter { @Resource private UserDetailsService userDetailsService; @Resource private CustSuccessHandler custSuccessHandler; @Resource private CustFailureHandler custFailureHandler; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() // 增加js静态资源的访问权限 .antMatchers("/login.html","/index.html","/login","/js/**").permitAll() // 给url配置角色访问权限 .antMatchers("/access/user").hasRole("USER") .antMatchers("/access/read").hasRole("READ") .antMatchers("/access/admin").hasRole("ADMIN") .anyRequest().authenticated() .and() .formLogin() .successHandler(custSuccessHandler) //执行验证成功的handler .failureHandler(custFailureHandler) // 执行验证失败后的handler // 指定使用自定义的登录界面 .loginPage("/login.html") .loginProcessingUrl("/login") .and() .csrf().disable(); } } 复制代码
使用@Resource注解将两个Handler注入,并且增加了js访问的白名单以及配置了验证成功和失败后的处理器
重启应用,并访问,如果页面显示加载jQyery失败,可以在Idea上Rebuild一下
页面报错ajax请求状态为已取消,并且无法获得相应
解决这个问题的办法需要在ajax代码中增加一行代码,即可解决问题
async: false 复制代码
重新启动应用
返回JSON格式数据
增加jackson依赖
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.8</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.8</version> </dependency> 复制代码
新增common包,增加一个Result类,用来表示返回的 JSON格式的数据
public class Result { private int code; private int error; private String msg; // 此处省略getter/setter方法 } 复制代码
改造CustSuccessHandler和CustFailureHandler
@Component public class CustSuccessHandler implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { // 登录的用户信息验证成功后执行的方法 response.setContentType("text/json;charset=utf-8"); // 设置返回的Json格式的结果 Result result = new Result(); result.setCode(0); result.setError(1000); result.setMsg("登录成功"); OutputStream outputStream = response.getOutputStream(); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.writeValue(outputStream,result); outputStream.flush(); outputStream.close(); } } 复制代码
@Component public class CustFailureHandler implements AuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { // 验证登录信息失败后执行的方法 response.setContentType("text/json;charset=utf-8"); // 设置返回的Json格式的结果 Result result = new Result(); result.setCode(0); result.setError(1001); result.setMsg("登录失败"); OutputStream outputStream = response.getOutputStream(); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.writeValue(outputStream,result); outputStream.flush(); outputStream.close(); } } 复制代码
重启应用,即可返回Json格式数据