没整合框架之前写登录注册两分钟,融入框架之后登录注册写两天,不过这也和我不熟悉shiro框架架构有关系。
首先准备登录注册页面:
登录页面:
注册页面:
大概先出个页面,等功能完善之后再去美化页面,毕竟我做个块级元素居中做了大半天。。
导入依赖pom.xml:
<!--shiro-->
<!--Subject用户-->
<!--SecurityManager管理所有用户-->
<!--Realm连接数据-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.2</version>
</dependency>
<!--shiro和thymeleaf整合-->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
控制器LoginController.java:
package com.lin.karley.Controller;
import com.alibaba.druid.support.json.JSONUtils;
import com.lin.karley.Pojo.User;
import com.lin.karley.Service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
@Controller
public class LoginController {
@Autowired(required = true)
private UserService userService;
@GetMapping(value = "/login")
public String login(){return "module/login";}
@ResponseBody
@PostMapping(value = "/shirologin")
public String loginCheck(String username, String password, boolean remember, HttpSession session){
String login = userService.login(username,password,remember,session);
HashMap<String, String> map = new HashMap<>();
map.put("res",login);
String jsonString = JSONUtils.toJSONString(map);
System.out.println(jsonString);
return jsonString;
}
@GetMapping("/register")
public String register(){return "module/register";}
@ResponseBody
@PostMapping(value = "/register")
public String registerCheck(User user)
{
String register = userService.register(user);
HashMap<String, String> map = new HashMap<>();
map.put("res",register);
System.out.println(JSONUtils.toJSONString(map));
return JSONUtils.toJSONString(map);
}
// @ResponseBody
@GetMapping("/logout")
public String logout(){
// ModelAndView mv = new ModelAndView();
Subject user = SecurityUtils.getSubject();
user.logout();
// mv.setViewName("redirect:/back_notes");
return "redirect:/back_notes";
}
}
业务层UserServiceImpl.java:
package com.lin.karley.Service.impl;
/**
* @Description Description
* @Author Karley LIn
* @Date Created in 2020/5/19
*/
import com.lin.karley.Common.ResponseCode;
import com.lin.karley.Pojo.User;
import com.lin.karley.Mapper.UserMapper;
import com.lin.karley.Service.UserService;
import com.lin.karley.Utils.PasswordUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpSession;
import java.util.*;
//@Component
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Autowired
PasswordUtil passwordUtil;
@Transactional
public String register(User user) {
if (user.getUsername().equals("karley")) {
user.setIsActive(1);
user.setIsSuperuser(1);
} else {
user.setIsActive(0);
user.setIsSuperuser(0);
}
String password = passwordUtil.encrypt(user.getPassword());
user.setPassword(password);
user.setCreatetime(new Date());
int res = userMapper.insert(user);
return ResponseCode.getMsgByStatus(res);
}
public String login(String username, String password, boolean remember,HttpSession session) {
//获取当前的用户
Subject subject = SecurityUtils.getSubject();
//封装用户的登录数据
UsernamePasswordToken token = new UsernamePasswordToken(username,password,remember);
try {
subject.login(token); //登录,如果没有异常说明ok
Subject currentSubject = SecurityUtils.getSubject();
User user = (User) subject.getPrincipal();
// Session session = currentSubject.getSession();
session.setAttribute("user",user);
System.out.println(user);
// 执行成功操作
System.out.println(ResponseCode.getMsgByStatus(3));
return ResponseCode.getMsgByStatus(3);
} catch (UnknownAccountException e) { //用户名不存在
// e.printStackTrace(); //执行操作
System.out.println(ResponseCode.getMsgByStatus(4));
return ResponseCode.getMsgByStatus(4);
}catch (IncorrectCredentialsException e){ //密码不存在
// e.printStackTrace();
System.out.println(ResponseCode.getMsgByStatus(2));
return ResponseCode.getMsgByStatus(2);
}
}
@Override
public User selectByUsername(String username) {
return this.userMapper.selectByUsername(username);
}
}
UserService、UserMapper接口类省略…
配置shiro
ShiroConfig.java:
package com.lin.karley.Config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
/**
* @Description Description
* @Author Karley LIn
* @Date Created in 2020/5/20
*/
@Configuration
public class ShiroConfig {
//ShrioFilterFactoryBean:3
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 设置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
//设置登录url
shiroFilterFactoryBean.setLoginUrl("/login");
shiroFilterFactoryBean.setUnauthorizedUrl("/");
//设置成功登陆打开的url
shiroFilterFactoryBean.setSuccessUrl("/back_notes");
//添加shiro的内置过滤器
// anon:无需认证可以访问
// auth:必须认真才能访问
// user:必须拥有记住我功能才能用
// perms:拥有对某个资源的权限
// role:拥有某个角色权限才能访问
LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();
// filterMap.put("/logout","auth");
// filterMap.put("/user/*","authc"); //认证才能访问的链接
// filterMap.put("/user/add","perms[user:add]"); //正常情况下未授权页面401
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
// bean.setUnauthorizedUrl("/noauth"); //未授权请求
// bean.setLoginUrl("/toLogin"); //设置登录页面
return shiroFilterFactoryBean;
}
//DetaultWebSecurityManager:2
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm, @Qualifier("rememberMeManager")RememberMeManager rememberMeManager){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联UserRealm
securityManager.setRealm(userRealm);
securityManager.setRememberMeManager(rememberMeManager);
return securityManager;
}
//创建realm对象,需要自定义:1
@Bean
public UserRealm userRealm(){
UserRealm userRealm = new UserRealm();
userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return userRealm;
}
//整合shiroDialect
@Bean(name = "shiroDialect")
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("sha-256");
hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
return hashedCredentialsMatcher;
}
// 记住我cookie
@Bean
public SimpleCookie rememberMeCookie(){
SimpleCookie remember = new SimpleCookie("remember");
remember.setHttpOnly(true);
remember.setPath("/");
remember.setMaxAge(2592000);
return remember;
}
// 记住我管理器
@Bean
public CookieRememberMeManager rememberMeManager(){
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
return cookieRememberMeManager;
}
@Bean
// 记住我filter
public FormAuthenticationFilter formAuthenticationFilter(){
FormAuthenticationFilter formAuthenticationFilter = new FormAuthenticationFilter();
formAuthenticationFilter.setRememberMeParam("remember");
return formAuthenticationFilter;
}
}
对了,还有注册密码加密工具类PasswordUtil.java:
package com.lin.karley.Utils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.stereotype.Component;
/**
* @Description Description
* @Author Karley LIn
* @Date Created in 2020/5/20
*/
@Component
public class PasswordUtil extends SimpleCredentialsMatcher {
//将传进来的密码加密
public String encrypt(String password) {
String sha256Hash = new Sha256Hash(password).toHex();
return sha256Hash;
}
}
登录认证时会走一个认证Info,UserRealm.java:
package com.lin.karley.Config;
import com.lin.karley.Pojo.User;
import com.lin.karley.Service.UserService;
import com.lin.karley.Utils.PasswordUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
/**
* @Description Description
* @Author Karley LIn
* @Date Created in 2020/5/20
*/
//自定义的UserRealm
public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
@Autowired
PasswordUtil passwordUtil;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("授权");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermission("user:add");
// 拿到当前登录用户的对象
Subject subject = SecurityUtils.getSubject();
User currentUser = (User) subject.getPrincipal();//取出user,取出object对象,强转成user
// 设置当前用户的权限
info.addStringPermission(String.valueOf(currentUser.getIsSuperuser()));
return info;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了认证");
UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
//连接真实数据库
User user = userService.selectByUsername(userToken.getUsername());
if (user == null){
//没有这个人 抛出一个UnknownAccountException异常
return null;
}
//密码认证shiro做
//可以加密,盐值
// 将用户信息封装在AuthenticationInfo
return new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
}
}
还没有做授权功能,把基本功能做完把页面完善就做权限功能。