发表于: 2020-07-24 22:55:00

1 1474


今天完成的事情:

1.使用SpringSecurity实现登录功能。

和用拦截器实现不同的是,使用SpringSecurity实现登录功能不需要我们手动写登录请求了。只需要在我们自己写的SecurityConfig配置类中加入:

@Override
protected void configure(HttpSecurity http) throws Exception {

http.authorizeRequests()
.antMatchers("/","/index.xml","/tologin","/login").permitAll()
.antMatchers("/u/**","/main").hasRole("account");

   http.formLogin()
.loginPage("/tologin")
.loginProcessingUrl("/login");
//.usernameParameter("user").passwordParameter("psw");
}

默认接收到的前端页面参数是username和password,如果不是这两个的话可以用.usernameParameter()方法来指定参数。


2.使用SpringSecurity实现记住登录功能。

使用SpringSecurity来实现记住登录的功能也很简单,只需要加上http.remember即可,之前使用拦截器的话要写大量代码来判断,现在只需要这么一句就可以了。

http.rememberMe().rememberMeParameter("remember-me");

前端代码:

<input type="checkbox" name="remember-me"

Springboot会自动帮我们生成一个cookie:


3.使用SpringSecurity实现注销功能。

想实现注销功能也很方便,不用像以前一样写logout方法,只需要添加一句:

http.logout().logoutSuccessUrl("/");

.logout()是开启注销功能,.logoutSuccessUrl是设置注销之后跳转的页面

前端代码:

<a class="nav-link" th:href="@{/logout}">注销</a>

还可以设置注销时删除cookie和session等。


前面都是用的储存在内存中的用户名和密码来模拟的,这边学习一下真正从数据库中获取用户名密码。

首先新建一个UserDetailsServiceImpl实现UserDetailsService接口,重写其中的loadUserByUsername方法:

package com.jnshu.springboot_mybatis.config;

import com.jnshu.springboot_mybatis.pojo.Account;
import com.jnshu.springboot_mybatis.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collection;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

@Autowired
   AccountService accountService;

   @Autowired
   PasswordEncoder passwordEncoder;

   @Override
   public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Account account = accountService.selectAccount(username);
       if (account == null) {
return null;
       } else {
Collection<GrantedAuthority> authorities = new ArrayList<>();
           authorities.add(new SimpleGrantedAuthority("ROLE_account"));
           User user = new User(account.getUsername(), passwordEncoder.encode(account.getPassword()), authorities);
           System.out.println("用户信息:" + user.getUsername() + "   " + passwordEncoder.encode(account.getPassword()) + "  " + user.getAuthorities());
           return user;
       }
}
}

接着配置SecurityConfig:

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
   /*auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
           .withUser("root").roles("account").password(new BCryptPasswordEncoder().encode("1234"));*/
}

接下来就可以用数据库中的用户进行登录了。

不过用之前的加密加盐工具加密过的密码就用不了了,springsecurity本身也有这个功能。

将之前的加密工具修改一下,实现PasswordEncoder接口,然后在验证的时候选择自定义的加密工具类即可。

package com.jnshu.springboot_mybatis.utils;

import org.springframework.security.crypto.password.PasswordEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;

public class Md5PasswordEncoder implements PasswordEncoder {

private final static String[] HEX_DIGITS = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};

   private String salt;

  public void setSalt(String salt) {
this.salt = salt;
   }

private static Md5PasswordEncoder instance = new Md5PasswordEncoder();

   public Md5PasswordEncoder() {
}
//以单例模式构造
   public static Md5PasswordEncoder getInstance() {
return instance;
   }


private String mergePasswordAndSalt(CharSequence password) {
if (password == null) {
password = "";
       }

if ((salt == null) || "".equals(salt)) {
return password.toString();
       } else {
return password + "{" + salt + "}";
       }
}

private String byteArrayToHexString(byte[] b) {
StringBuilder resultSb = new StringBuilder();
       for (byte value : b) {
resultSb.append(byteToHexString(value));
       }
return resultSb.toString();
   }

private String byteToHexString(byte b) {
int n = b;
       if (n < 0) {
n = 256 + n;
       }
int d1 = n / 16;
       int d2 = n % 16;
       return HEX_DIGITS[d1] + HEX_DIGITS[d2];
   }

/**
    * MD5加密
    *
    * @param rawPassword 原始密码
    * @return 加密后的md5密文
    */
   @Override
   public String encode(CharSequence rawPassword) {
String result = null;
       try {
String algorithm = "MD5";
           MessageDigest md = MessageDigest.getInstance(algorithm);
           result = byteArrayToHexString(md.digest(mergePasswordAndSalt(rawPassword).getBytes(StandardCharsets.UTF_8)));
       } catch (Exception ignored) {
}
return result;
   }

/**
    * 密码比较
    *
    * @param rawPassword     原始密码
    * @param encodedPassword 加密后的密码
    * @return boolean
    */
   @Override
   public boolean matches(CharSequence rawPassword, String encodedPassword) {
return encodedPassword.equals(encode(rawPassword));
   }
}

SecurityConfig配置类:

加密方式改为自定义md5加密。




返回列表 返回列表
评论

    分享到