SpringSecurity做简单登陆

阅读: 评论:0

SpringSecurity做简单登陆

SpringSecurity做简单登陆

一、要解决的问题

  本篇要解决的问题

  • 项目级别统一拦截请求
  • 注册加密
  • 登录校验
  • 登录成功/失败返回自定义信息
  • 自定义用户信息

二、原理

  Spring Boot项目中引入Spring Security,通过WebSecurityConfigurerAdapter来实现请求的统一拦截,拦截到请求后,通过UserDetailsService来查询数据库中存储的用户信息,比对登录请求传输的信息,来确定登录成功与否。

三、实战

1.引入Spring Security

 

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

2.自定义WebSecurityConfigurerAdapter统一拦截请求

 

/*** @EnableWebSecurity:此注解会启用Spring Security*/
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate MyUserDetailService myUserDetailService;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(myUserDetailService);
//        auth.inMemoryAuthentication()
//                .passwordEncoder(passwordEncoder())
//                .withUser("user_1").password(passwordEncoder().encode("123456")).roles("USER")
//                .and()
//                .withUser("user_2").password(passwordEncoder().encode("123456")).roles("ADMIN");}/*** 密码加密*/@Beanpublic BCryptPasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}@Autowiredprivate EvolutionaryAuthenticationSuccessHandler evolutionaryAuthenticationSuccessHandler;@Autowiredprivate Failhandler failhandler;//    /**
//     * 1)HttpSecurity支持cors。
//     * 2)默认会启用CRSF,此处因为没有使用thymeleaf模板(会自动注入_csrf参数),
//     * 要先禁用csrf,否则登录时需要_csrf参数,而导致登录失败。
//     * 3)antMatchers:匹配 "/" 路径,不需要权限即可访问,匹配 "/user" 及其以下所有路径,
//     *  都需要 "USER" 权限
//     * 4)配置登录地址和退出地址
//     */
//    @Override
//    protected void configure(HttpSecurity http) throws Exception {
//        http
//            .cors().and()
//            .csrf().disable()
//            .authorizeRequests()
//            .antMatchers("/").permitAll()
//            .antMatchers("/user/**").hasRole("USER")
//            .and()
//            .formLogin().loginPage("/login").defaultSuccessUrl("/hello")
//            .and()
//            .logout().logoutUrl("/logout").logoutSuccessUrl("/login");
//    }@Overrideprotected void configure(HttpSecurity http) throws Exception {http.formLogin()  //表单登录//.loginPage("/evolutionary-loginIn.html").loginPage("/logintype") //如果需要身份认证则跳转到这里.loginProcessingUrl("/login").successHandler(evolutionaryAuthenticationSuccessHandler).failureHandler(failhandler).and().authorizeRequests().antMatchers("/logintype")//不校验我们配置的登录页面.permitAll().anyRequest().authenticated().and().csrf().disable();}
}

3.自定义UserDetailsService查询数据库中用户信息

 

@Service
public class MyUserDetailService implements UserDetailsService {@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {//从数据库查询用户信息
//        UserInfoBean userInfo = User(username);
//        if (userInfo == null){
//            throw new UsernameNotFoundException("用户不存在!");
//        }//查询权限信息
//        List<SimpleGrantedAuthority> simpleGrantedAuthorities = Roles());//返回Spring Security框架提供的User或者自定义的MyUser(implements UserDetails)return new MyUser(username, Password(), simpleGrantedAuthorities);return new User(username, new BCryptPasswordEncoder().encode("987654"), wArrayList());}/*** 权限字符串转化** 如 "USER,ADMIN" -> SimpleGrantedAuthority("USER") + SimpleGrantedAuthority("ADMIN")** @param roleStr 权限字符串*/private List<SimpleGrantedAuthority> createAuthorities(String roleStr){String[] roles = roleStr.split(",");List<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();for (String role : roles) {simpleGrantedAuthorities.add(new SimpleGrantedAuthority(role));}return simpleGrantedAuthorities;}
}

4.密码加密

  密码加密简单说明下。密码加密分两个部分,注册时给存储到数据库的密码加密和登录验证时将拿到的密码加密与数据库中密码比对。Spring Security提供了几种加密方式,当然也可自定义,此处选用BCryptPasswordEncoder。
  BCryptPasswordEncoder相关知识:用户表的密码通常使用MD5等不可逆算法加密后存储,为防止彩虹表破解更会先使用一个特定的字符串(如域名)加密,然后再使用一个随机的salt(盐值)加密。特定字符串是程序代码中固定的,salt是每个密码单独随机,一般给用户表加一个字段单独存储,比较麻烦。BCrypt算法将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而无需单独处理salt问题。

1)注册时给密码加密

注册接口中加密密码:

 

@Service
public class UserService {@Autowiredprivate UserInfoMapper userInfoMapper;public boolean insert(UserInfoBean userInfo){encryptPassword(userInfo);if(userInfoMapper.insert(userInfo)==1)return true;elsereturn false;};private void encryptPassword(UserInfoBean userInfo){String password = Password();password = new BCryptPasswordEncoder().encode(password);userInfo.setPassword(password);}
}

2)登录时密码加密校验

只需在WebSecurityConfigurerAdapter的子类中指定密码的加密规则即可,Spring Security会自动将密码加密后与数据库比对。

 

@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(myUserDetailService).passwordEncoder(passwordEncoder());}/*** 密码加密*/@Beanpublic BCryptPasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}

5.自定义用户登录流程

  要实现当用户是html结尾的请求就跳转到默认的登录页面或者指定的登录页,用户是restFul请求时就返回json数据。备注:此处的校验逻辑是以html后缀来校验,如果集成其他模板引擎可根据需要修改。
1)先定义实现以上需求的controller逻辑

 

private RequestCache requestCache = new HttpSessionRequestCache();private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();@Autowiredprivate SecurityProperties securityProperties;@RequestMapping("/logintype")@ResponseBody@ResponseStatus(code = HttpStatus.UNAUTHORIZED)public String requireAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException {SavedRequest savedRequest = Request(request, response);if (savedRequest != null) {String targetUrl =  RedirectUrl();logger.info("引发跳转的请求是:" + targetUrl);if (dsWithIgnoreCase(targetUrl, ".html")) {redirectStrategy.sendRedirect(request, response, Brower().getLoginPage());}}return "请登录!";}@GetMapping("/login_html")public String loginHtml(){return "login";}@PostMapping("/login")public void login(){}

2)定义不同登录页面的配置类

 

@Configuration
@ConfigurationProperties(prefix = "evolutionary.security")
public class SecurityProperties {private BrowerProperties brower = new BrowerProperties();public BrowerProperties getBrower() {return brower;}public void setBrower(BrowerProperties brower) {this.brower = brower;}
}

 

public class BrowerProperties {private String loginPage = "/login_html";//默认跳转的接口//    private LoginInType loginInType = LoginInType.JSON;public String getLoginPage() {return loginPage;}public void setLoginPage(String loginPage) {this.loginPage = loginPage;}//    public LoginInType getLoginInType() {
//        return loginInType;
//    }
//
//    public void setLoginInType(LoginInType loginInType) {
//        this.loginInType = loginInType;
//    }
}

可配置的登录页面

 

#配置登录页面接口
#evolutionary.security.brower.loginPage = /login_html
#evolutionary.security.brower.loginInType=REDIRECT

3)默认的登录页面login.html

 

<html xmlns:th="">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>登录 | SpringForAll - Spring Security</title><link href=".3.7/css/bootstrap.css" rel="stylesheet">
</head>
<body style="background-color: #f1f1f1; padding-bottom: 0">
<div class="container" style="margin-top: 60px"><div class="row" style="margin-top: 100px"><div class="col-md-6 col-md-offset-3"><div class="panel panel-primary"><div class="panel-heading"><h3 class="panel-title"><span class="glyphicon glyphicon-console"></span> Login</h3></div><div class="panel-body"><form th:action="@{/login}" method="post"><div class="form-group" style="margin-top: 30px"><div class="input-group col-md-6 col-md-offset-3"><div class="input-group-addon"><span class="glyphicon glyphicon-user"></span></div><input type="text" class="form-control" name="username" id="username" placeholder="账号"></div></div><div class="form-group "><div class="input-group col-md-6 col-md-offset-3"><div class="input-group-addon"><span class="glyphicon glyphicon-lock"></span></div><input type="password" class="form-control" name="password" id="password"placeholder="密码"></div></div><br><div class="form-group"><div class="input-group col-md-6 col-md-offset-3 col-xs-12 "><button type="submit" class="btn btn-primary btn-block">登录</button></div></div></form></div></div></div></div>
</div>
</body>
</html>

4)修改认证逻辑的代码见文末

6.自定义登录成功处理

默认情况下Spring Security登录成功后会跳到之前引发登录的请求。修改为登录成功返回json信息,只需实现AuthenticationSuccessHandler接口的onAuthenticationSuccess方法:

 

@Component("evolutionaryAuthenticationHandler")
public class EvolutionaryAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {private Logger logger = Logger(getClass());/*** spring MVC 启动的时候会为我们注册一个objectMapper*/@Autowiredprivate ObjectMapper objectMapper;@Autowiredprivate SecurityProperties securityProperties;/*** 登录成功会调用该方法* @param request* @param response* @param authentication* @throws IOException* @throws ServletException*/@Overridepublic void onAuthenticationSuccess(HttpServletRequest request,HttpServletResponse response,Authentication authentication) throws IOException, ServletException {logger.info("登录成功!");if (LoginInType.JSON.Brower().getLoginInType())) {response.setContentType("application/json;charset=UTF-8");Writer().write(objectMapper.writeValueAsString(authentication));}AuthenticationSuccess(request, response, authentication);}}
}

 

@Component("failhandler")
public class Failhandler extends SimpleUrlAuthenticationFailureHandler {@Autowiredprivate ObjectMapper objectMapper;public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throwsIOException, ServletException {response.setContentType("application/json;charset=UTF-8");Writer().write(objectMapper.writeValueAsString(exception));}}

 

 

本文发布于:2024-02-03 00:22:06,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170689092847427.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:简单   SpringSecurity
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23