2.2應(yīng)用配置文件
#Logging_configlogging.level.root=INFOlogging.level.org.springframework.web=WARNlogging.file=minibox.log#server_config#使用了SSL,并且在ldap配置中使用了ldaps,這里同時也需要把AD的證書導(dǎo)入到server.keystore中。具體的可以查看java的keytool工具server.port=8443server.ssl.key-store=classpath:server.keystoreserver.ssl.key-store-password=miniboxserver.ssl.key-password=minibox#jwt#jwt加解密時使用的keyjwt.key=minibox#ldap_config#ldap配置信息,注意這里的userDn一定要寫這種形式。referral設(shè)置為follow,說不清用途,似乎只有連接AD時才需要配置ldap.url=ldaps://192.168.227.128:636ldap.base=ou=Employees,dc=minibox,dc=comldap.userDn=cn=Administrator,cn=Users,dc=minibox,dc=comldap.userPwd=QQ[email protected]3.Spring主配置類
package an;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.Bean;import org.springframework.ldap.core.LdapTemplate;import org.springframework.ldap.core.support.LdapContextSource;@SpringBootApplication//相當于@Configuration,@EnableAutoConfiguration,@ComponentScanpublic class Application { /* * SpringLdap配置。通過@Value注解讀取之前配置文件中的值 */ @Value("${ldap.url}") private String ldapUrl; @Value("${ldap.base}") private String ldapBase; @Value("${ldap.userDn}") private String ldapUserDn; @Value("${ldap.userPwd}") private String ldapUserPwd; @Value("${ldap.referral}") private String ldapReferral; /* *SpringLdap的javaConfig注入方式 */ @Bean public LdapTemplate ldapTemplate() { return new LdapTemplate(contextSourceTarget()); } @Bean public LdapContextSource contextSourceTarget() { LdapContextSource ldapContextSource = new LdapContextSource(); ldapContextSource.setUrl(ldapUrl); ldapContextSource.setBase(ldapBase); ldapContextSource.setUserDn(ldapUserDn); ldapContextSource.setPassword(ldapUserPwd); ldapContextSource.setReferral(ldapReferral); return ldapContextSource; } public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); }}3.1提供認證服務(wù)的類
package an.auth;import javax.naming.directory.Attributes;import javax.naming.directory.DirContext;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;import org.springframework.ldap.NamingException;import org.springframework.ldap.core.AttributesMapper;import org.springframework.ldap.core.LdapTemplate;import org.springframework.ldap.support.LdapUtils;import org.springframework.web.bind.annotation.CrossOrigin;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.serializer.SerializerFeature;import static org.springframework.ldap.query.LdapQueryBuilder.query;import java.util.Date;import java.util.HashMap;import java.util.Map;import an.entity.Employee;import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;@RestController@RequestMapping("/auth")public class JwtAuth { //jwt加密密匙 @Value("${jwt.key}") private String jwtKey; //域名后綴 @Value("${ldap.domainName}") private String ldapDomainName; //ldap模板 @Autowired private LdapTemplate ldapTemplate; /** * 將域用戶屬性通過EmployeeAttributesMapper填充到Employee類中,返回一個填充信息的Employee實例 */ private class EmployeeAttributesMapper implements AttributesMapper<Employee> { public Employee mapFromAttributes(Attributes attrs) throws NamingException, javax.naming.NamingException { Employee employee = new Employee(); employee.setName((String) attrs.get("sAMAccountName").get()); employee.setDisplayName((String) attrs.get("displayName").get()); employee.setRole((String) attrs.get("memberOf").toString()); return employee; } } /** * @param username 用戶提交的名稱 * @param password 用戶提交的密碼 * @return 成功返回加密后的token信息,失敗返回錯誤HTTP狀態(tài)碼 */ @CrossOrigin//因為需要跨域訪問,所以要加這個注解 @RequestMapping(method = RequestMethod.POST) public ResponseEntity<String> authByAd( @RequestParam(value = "username") String username, @RequestParam(value = "password") String password) { //這里注意用戶名加域名后綴 userDn格式:[email protected] String userDn = username + ldapDomainName; //token過期時間 4小時 Date tokenExpired = new Date(new Date().getTime() + 60*60*4*1000); DirContext ctx = null; try { //使用用戶名、密碼驗證域用戶 ctx = ldapTemplate.getContextSource().getContext(userDn, password); //如果驗證成功根據(jù)sAMAccountName屬性查詢用戶名和用戶所屬的組 Employee employee = ldapTemplate .search(query().where("objectclass").is("person").and("sAMAccountName").is(username), new EmployeeAttributesMapper()) .get(0); //使用Jwt加密用戶名和用戶所屬組信息 String compactJws = Jwts.builder() .setSubject(employee.getName()) .setAudience(employee.getRole()) .setExpiration(tokenExpired) .signWith(SignatureAlgorithm.HS512, jwtKey).compact(); //登錄成功,返回客戶端token信息。這里只加密了用戶名和用戶角色,而displayName和tokenExpired沒有加密 Map<String, Object> userInfo = new HashMap<String, Object>(); userInfo.put("token", compactJws); userInfo.put("displayName", employee.getDisplayName()); userInfo.put("tokenExpired", tokenExpired.getTime()); return new ResponseEntity<String>(JSON.toJSONString(userInfo , SerializerFeature.DisableCircularReferenceDetect) , HttpStatus.OK); } catch (Exception e) { //登錄失敗,返回失敗HTTP狀態(tài)碼 return new ResponseEntity<String>(HttpStatus.UNAUTHORIZED); } finally { //關(guān)閉ldap連接 LdapUtils.closeContext(ctx); } }}新聞熱點
疑難解答