自定义用户认证逻辑: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