自定義用戶認證邏輯:git
1,處理用戶信息獲取,2,用戶校驗,3密碼的加密解密github
新建:MyUserDetailService類,實現UserDetailsService接口。spring
UserDetailsService接口代碼:只有一個方法,經過用戶名獲取用戶信息,返回UserDetail安全
public interface UserDetailsService { UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; }
UserDetail:記錄了 帳戶是否啓用、帳戶是否過時、密碼是否過時、帳戶是否鎖定、權限集合信息app
public interface UserDetails extends Serializable { // ~ Methods // ======================================================================================================== /** * Returns the authorities granted to the user. Cannot return <code>null</code>. * * @return the authorities, sorted by natural key (never <code>null</code>) */ Collection<? extends GrantedAuthority> getAuthorities(); /** * Returns the password used to authenticate the user. * * @return the password */ String getPassword(); /** * Returns the username used to authenticate the user. Cannot return <code>null</code> * . * * @return the username (never <code>null</code>) */ String getUsername(); /** * Indicates whether the user's account has expired. An expired account cannot be * authenticated. * * @return <code>true</code> if the user's account is valid (ie non-expired), * <code>false</code> if no longer valid (ie expired) */ boolean isAccountNonExpired(); /** * Indicates whether the user is locked or unlocked. A locked user cannot be * authenticated. * * @return <code>true</code> if the user is not locked, <code>false</code> otherwise */ boolean isAccountNonLocked(); /** * Indicates whether the user's credentials (password) has expired. Expired * credentials prevent authentication. * * @return <code>true</code> if the user's credentials are valid (ie non-expired), * <code>false</code> if no longer valid (ie expired) */ boolean isCredentialsNonExpired(); /** * Indicates whether the user is enabled or disabled. A disabled user cannot be * authenticated. * * @return <code>true</code> if the user is enabled, <code>false</code> otherwise */ boolean isEnabled(); }
MyUserDetailService:dom
package com.imooc.security.browser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.authority.AuthorityUtils; 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.Component; /** * UserDetailsService是SpringSecurity的一個接口, * 只有一個方法:根據用戶名獲取用戶詳情 * ClassName: MyUserDetailService * @Description: TODO * @author lihaoyang * @date 2018年2月28日 */ @Component public class MyUserDetailService implements UserDetailsService{ private Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private PasswordEncoder passwordEncoder; /** * UserDetails接口,實際能夠本身實現這個接口,返回本身的實現類 */ @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { logger.info("登陸用戶名:"+username); //根據用戶名查詢用戶信息 //User:springsecurity 對 UserDetails的一個實現 //爲了演示在這裏用passwordEncoder加密一下密碼,實際中在註冊時就加密,此處直接拿出密碼 String password = passwordEncoder.encode("123456"); System.err.println("加密後密碼: "+password); //參數:用戶名|密碼|是否啓用|帳戶是否過時|密碼是否過時|帳戶是否鎖定|權限集合 return new User(username,password,true,true,true,true,AuthorityUtils.commaSeparatedStringToAuthorityList("admin")); } }
在BrowserSecurityConfig裏配置PasswordEncoder,用來加密密碼的一個接口:ide
@Configuration //這是一個配置 public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter{ //注意是org.springframework.security.crypto.password.PasswordEncoder @Bean public PasswordEncoder passwordencoder(){ //BCryptPasswordEncoder implements PasswordEncoder return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity http) throws Exception { //實現須要認證的接口跳轉表單登陸,安全=認證+受權 //http.httpBasic() //這個就是默認的彈框認證 http.formLogin() //表單認證 .and() .authorizeRequests() //下邊的都是受權的配置 .anyRequest() //任何請求 .authenticated(); //都須要身份認證 } }
PasswordEncoder代碼:一個加密方法,一個匹配方法,注意是org.springframework.security.crypto.password包裏的接口,這個接口的實現類會給加密的密碼隨機加鹽,因此同樣的密碼每次加密出來是不同的,更安全。如123456加密2次:加密
加密後密碼: $2a$10$BChH.C4.X8MYuI1mHFoOkefWhOsad7SvhZedHFt1OG4vjSu.z9weCspa
加密後密碼: $2a$10$YUbz.miE5C0aAcuU1FnHSu/U.Qm/BujTNw6X7S5i4/6AhjyDc6suKcode
package org.springframework.security.crypto.password; /** * Service interface for encoding passwords. * * The preferred implementation is {@code BCryptPasswordEncoder}. * * @author Keith Donald */ public interface PasswordEncoder { /** * Encode the raw password. Generally, a good encoding algorithm applies a SHA-1 or * greater hash combined with an 8-byte or greater randomly generated salt. */ String encode(CharSequence rawPassword); /** * Verify the encoded password obtained from storage matches the submitted raw * password after it too is encoded. Returns true if the passwords match, false if * they do not. The stored password itself is never decoded. * * @param rawPassword the raw password to encode and match * @param encodedPassword the encoded password from storage to compare with * @return true if the raw password, after encoding, matches the encoded password from * storage */ boolean matches(CharSequence rawPassword, String encodedPassword); }
訪問:http://localhost:8080/user
輸入正確的密碼123456:能夠訪問user查詢服務
完整代碼GitHub:https://github.com/lhy1234/spring-security