已經有一個多月沒有更新這個系列的文章了。本期目標是完成基礎的手腳架。html
號外前端
本項目github倉庫:github.com/pc859107393…java
本項目國內碼雲倉庫:git.oschina.net/859107393/M…git
本系列爲連載文章。固然若是你沒有spring基礎,建議你先看看個人java手把手教程github
有興趣交流springboot進行快速開發的同窗能夠加一下下面的企鵝羣。web
正文開始spring
首先咱們須要簡單的看看咱們項目須要的支援:數據庫
數據庫相關:apache
核心依賴:springjson
固然僅僅擁有這些,還不足以完成一個項目的搭建,可是這些是咱們構建的基石。使咱們更加快速的開發。
怎樣來組裝一個基礎的項目,咱們在上一期已經講完了,本期咱們接着要完成一個基礎項目框架,同時呢還應該有一個基礎項目構建的思考。
1.怎麼完成安全校驗的登陸
其實這個在上一季的項目中已經探討完成了,這一季只是說老生重談。甚至來說,登陸是一個簡單的過程,卻不是個容易的東西。
首先咱們應該作到:可靠、安全、有效。詳細說一下就是:傳輸過程加密,數據存儲加密,信息服務器存放,前端單純的展現。那麼咱們常規的處理手段有:
具體的代碼以下:
@Controller
@Api(description = "外層信息,無需Shiro接管,集成文件下載控制器")
public class MainController{
@PostMapping(value = "/login", produces = MediaType.TEXT_HTML_VALUE)
@ApiOperation(value = "/login", notes = "登陸後臺系統")
public String login(@ApiParam(hidden = true) ModelMap map, @ApiParam(hidden = true) ShiroHttpServletRequest request, @ApiParam(value = "用戶名不能爲空,不然不容許登陸" , required = true) @RequestParam(value = "userLogin", required = false) String userLogin, @ApiParam(value = "用戶密碼不能爲空且必須爲16位小寫MD5,不然不容許登陸" , required = true) @RequestParam(value = "userPass", required = false) String userPass) {
User result = null;
try {
//1.獲得Subject
Subject subject = SecurityUtils.getSubject();
//2.調用登陸方法
UsernamePasswordToken token = new UsernamePasswordToken(userLogin, userPass);
subject.login(token);//當這一代碼執行時,就會自動跳入到AuthRealm中認證方法
result = (User) subject.getPrincipal();
subject.getSession().setAttribute("userInfo", result);
return "redirect:/endSys/index";
} catch (Exception e) {
e.printStackTrace();
LogE.getInstance(this.getClass()).logOutLittle(e.getMessage());
map.addAttribute("msg", e.getMessage());
return "login";
}
}
@GetMapping(path = "logOut", produces = MediaType.TEXT_HTML_VALUE)
@ApiOperation(value = "退出登陸", notes = "退出登陸,清空session")
public String logOut() {
Subject subject = SecurityUtils.getSubject();
if (subject.isAuthenticated()) {
subject.getSession().removeAttribute("userInfo");
subject.logout(); // session 會銷燬,在SessionListener監聽session銷燬,清理權限緩存
}
return "redirect:/";
}
}
public class ShiroRealm extends AuthorizingRealm {
@Autowired
private UserServiceImpl userService;
/* * 登陸信息和用戶驗證信息驗證(non-Javadoc) * @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken) */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UsernamePasswordToken user = (UsernamePasswordToken) token;
LogE.getInstance(ShiroRealm.class).logOutLittle("開始登陸====>\n用戶爲:" + user.getUsername());
String userLogin = user.getUsername();
char[] password = user.getPassword();
User loginResult = null;
try {
loginResult = userService.login(userLogin, new String(password));
} catch (Exception e) {
e.printStackTrace();
LogE.getInstance(ShiroRealm.class).logOutLittle("登陸異常結束====>\n用戶爲:" + user.getUsername());
throw new AuthenticationException(e.getMessage());
}
LogE.getInstance(ShiroRealm.class).logOutLittle("登陸成功====>\n用戶爲:" + user.getUsername());
return new SimpleAuthenticationInfo(loginResult, user.getPassword(), this.getName());
}
}
public class MyCredentialsMatcher extends SimpleCredentialsMatcher {
/** * 密碼比較方法,有本身的登陸校驗方法,故此繞過校驗 * * @param token * @param info * @return */
@Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
return true;
}
}複製代碼
固然,其餘的代碼,都不是那麼核心,咱們主要是圍繞着Shiro來闡述咱們的登陸。
爲何咱們的登陸和註銷地址不要Shiro接管呢?由於不管在登陸或註銷的時候有沒有用戶,咱們都會執行對應的操做來分別存放用戶信息或者清除用戶信息。
可是僅僅有這個就能完成登錄校驗?錯!錯!錯! 咱們須要把shiro接管的頁面都歸入管理範圍內。也就會產生spring相關的設置,這些,在咱們上一季都是有講到過。可是上一季是XML配置,這一次咱們是java配置。
@Configuration
public class ShiroConfig {
@Bean
public ShiroRealm realm() {
ShiroRealm myShiroRealm = new ShiroRealm();
MyCredentialsMatcher matcher = new MyCredentialsMatcher();
myShiroRealm.setCredentialsMatcher(matcher); //設置解密規則
return myShiroRealm;
}
//SecurityManager 是 Shiro 架構的核心,經過它來連接Realm和用戶(文檔中稱之爲Subject.)
@Bean
public DefaultSecurityManager securityManager() {
DefaultSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm()); //將Realm注入到SecurityManager中。
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setGlobalSessionTimeout(1800000); //默認三十分鐘
// Cookie cookie = new SimpleCookie(); //設置cookie
// cookie.setName("sid"); //java默認值是JSESSIONID
// cookie.setDomain("acheng1314.cn"); //cookie做用域
// cookie.setMaxAge(1800); //cookie超時時間30分鐘
// cookie.setHttpOnly(true);
//
// sessionManager.setSessionIdCookie(cookie);
// sessionManager.setSessionIdCookieEnabled(true);
//session會話驗證
// ExecutorServiceSessionValidationScheduler sessionValidationScheduler = new ExecutorServiceSessionValidationScheduler();
// sessionValidationScheduler.setInterval(3600000);
// sessionValidationScheduler.setSessionManager(sessionManager);
//
// sessionManager.setSessionValidationScheduler(sessionValidationScheduler);
// sessionManager.setSessionValidationSchedulerEnabled(true);
securityManager.setSessionManager(sessionManager); //此處已經自動持有DefaultWebSessionManager
return securityManager;
}
//在這裏配置url訪問規則
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/favicon.ico", "anon");
filterChainDefinitionMap.put("/static/*/**", "anon");
//authc表示須要驗證身份才能訪問,還有一些好比anon表示不須要驗證身份就能訪問等。
filterChainDefinitionMap.put("/druid/*/**", "authc");
filterChainDefinitionMap.put("/endSys/*/**", "authc");
filterChainDefinitionMap.put("/swagger-ui.html/*/**", "authc");
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setSuccessUrl("/endSys/index");
// shiroFilterFactoryBean.setUnauthorizedUrl("/403"); //這裏設置403並不會起做用,參考http://www.jianshu.com/p/e03f5b54838c
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
}複製代碼
咱們首先告訴spring框架這個是咱們框架的設置,須要載入。 而後接着在這個設置裏面配置對應的bean(ShiroRealm、DefaultSecurityManager、ShiroFilterFactoryBean)來實現相應的調度規則。
一些具體的細節,如:前端登陸頁面、數據庫操做等等,請查閱github倉庫代碼或者訪問碼雲
到目前這裏,咱們能夠實現登陸到系統首頁了:http://localhost:8181/login
登陸成功後,簡單的主頁以下:
悄悄的告訴你,我後端主頁使用了zDrag來實現網頁內部窗體管理。
固然到了這裏仍是有點小問題,那就是咱們用戶信息過時後,咱們點擊菜單會產生內部窗體登陸(登陸成功後再點擊菜單會回到正確界面)咱們添加一個js方法就能解決這個小問題。
總結
這一期主要討論了手腳腳須要的東西。
下期預告
下期目標是產生代碼生成器和菜單樹。
若是你承認我所作的事情,而且認爲我作的事對你有必定的幫助,但願你也能打賞我一杯咖啡,謝謝。