本代码仅后台,前台代码使用前后台分离自己配置
一、引入shiro包
implementation("org.apache.shiro:shiro-core:$ShiroVersion",
"org.apache.shiro:shiro-ehcache:$ShiroVersion",
"org.apache.shiro:shiro-web:$ShiroVersion",
"org.apache.shiro:shiro-quartz:$ShiroVersion",
"org.apache.shiro:shiro-spring:1.3.2")
quartz引入之后必须配置,否则报错,暂时不用可在application注解上将其去掉
@SpringBootApplication(exclude = QuartzAutoConfiguration.class)
二、shiro配置ShiroConfig.java
import com.trgis.firstproject.framework.shiro.MyShiroRealm;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @author ZHAO
* @date 2019/1/8 17:49
*/
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 必须设置 SecurityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
shiroFilterFactoryBean.setLoginUrl("/login.html");
// 登录成功后要跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/index.html");
// 未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
//自定义拦截器
Map<String, Filter> filters = new LinkedHashMap<String, Filter>();
//限制同一帐号同时在线的个数。
//filtersMap.put("kickout", kickoutSessionControlFilter());
shiroFilterFactoryBean.setFilters(filters);
// 权限控制map.
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/login", "anon");
filterMap.put("/index", "anon");
filterMap.put("/static/**", "anon");
filterMap.put("/templates/**", "authc");
// filterMap.put("/webjars/**", "anon");
filterMap.put("/druid/**", "anon");
filterMap.put("/api/**", "anon");
filterMap.put("/**/*.css", "anon");
filterMap.put("/**/*.js", "anon");
filterMap.put("/**/*.html", "anon");
filterMap.put("/images/**", "anon");
filterMap.put("/fonts/**", "anon");
// filterMap.put("/swagger/**", "anon");
// filterMap.put("/favicon.ico", "anon");
// filterMap.put("/", "anon");
shiroFilterFactoryBean
.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
@Bean
public SessionManager sessionManager(){
DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
sessionManager.setSessionValidationSchedulerEnabled(true);
sessionManager.setSessionIdCookieEnabled(false);
sessionManager.setGlobalSessionTimeout(2*3600000);
return sessionManager;
}
@Bean
public SecurityManager securityManager(SessionManager sessionManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
securityManager.setSessionManager(sessionManager);
return securityManager;
}
@Bean
public MyShiroRealm myShiroRealm(){
return new MyShiroRealm();
}
/**
* cookie对象;
* @return
*/
public SimpleCookie rememberMeCookie(){
//这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
//<!-- 记住我cookie生效时间30天 ,单位秒;-->
simpleCookie.setMaxAge(2592000);
return simpleCookie;
}
/**
* cookie管理对象;记住我功能
* @return
*/
public CookieRememberMeManager rememberMeManager(){
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(rememberMeCookie());
//rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
cookieRememberMeManager.setCipherKey(Base64.decode("3AvVhmFLUs0KTA3Kprsdag=="));
return cookieRememberMeManager;
}
}
三、自定义realm MyShiroRealm.java
import com.trgis.firstproject.modules.sys.entity.User;
import com.trgis.firstproject.modules.sys.service.UserService;
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.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.HashSet;
import java.util.Set;
/**
* @author ZHAO
* @date 2019/1/8 18:22
*/
public class MyShiroRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 授权用户权限
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
User user = (User) SecurityUtils.getSubject().getPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获取用户角色
Set<String> roleSet = new HashSet<>();
roleSet.add("100002");
info.setRoles(roleSet);
//获取用户权限
Set<String> permissionSet = new HashSet<>();
permissionSet.add("权限添加");
permissionSet.add("权限删除");
info.setStringPermissions(permissionSet);
return info;
}
/**
* 验证用户身份
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
String username = token.getUsername();
String password = String.valueOf(token.getPassword());
User user = userService.findByAccount(username);
// 抛出异常,在登陆处LoginController处处理(subject.login()接收异常)
if(user.getDelFlag() == 1){
throw new UnknownAccountException("验证未通过,用户无效!");
}
if(user == null || !user.getPassword().equals(password)) {
throw new UnknownAccountException("验证 未通过,用户名密码错误!");
}
User userInfo = new User();
userInfo.setAccount(user.getAccount());
userInfo.setPassword(user.getPassword());
user.setDelFlag(user.getDelFlag());
setSession("user",userInfo);
return new SimpleAuthenticationInfo(user, password, getName());
}
/**
* 将一些数据放到ShiroSession中,以便于其它地方使用,将用户存放到session中
* @see // 比如Controller,使用时直接用HttpSession.getAttribute(key)就可以取到
*/
private void setSession(Object key, Object value){
Subject currentUser = SecurityUtils.getSubject();
if(currentUser != null){
Session session = currentUser.getSession();
System.out.println(session.getId());
if(null != session){
// 2小时
session.setTimeout(7200000);
session.setAttribute(key, value);
}
}
}
}
四、登陆控制层LoginController.java
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
/**
* 登陆控制层
* @author ZHANG
* @date 2019/01/08
*/
@Controller
public class LoginController {
@RequestMapping(value = "/login", method={RequestMethod.POST, RequestMethod.GET})
public void userLogin(@RequestParam("account") String username, @RequestParam("password") String password) {
String userAccount = username;
String userPassword = password;
System.out.println(111 + userAccount + userPassword);
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
token.setRememberMe(true);
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
} catch (UnknownAccountException e) {
System.out.println("账户错误");
}
}
}
五、实体类User.java
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
* 系统用户实体类
* @author ZHANG
* @date 2019/01/08
*/
@Entity
@Table(name = "users")
public class User implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@GenericGenerator(name = "generator", strategy = "native")
@Column(name = "userid", unique = true, nullable = false)
private Long userid;
/**
* 用户账号名
*/
@Column(unique=true)
private String account;
/**
* 密码默认值为123456
*/
@Column
private String password = "123456";
/**
* 用户名称
*/
@Column
private String name;
/**
* 用户性别
*/
@Column
private String gender;
/**
* 用户电子邮件
*/
@Column
private String email;
/**
* 用户电话号码
*/
@Column
private String telephone;
/**
* @是否是内部用户 0.是 1否
*/
@Column
private Integer isInner = 0;
/**
* 创建时间
*/
@Column
private Date creatTime;
/**
* 登录时间
*/
private Date loginTime;
/**
* 上次登录时间
*/
private Date lastLoginTime;
/**
* 最后登录失败时间
*/
private Date lastLoginErrorTime;
/**
* 登录错误次数
*/
private Integer loginErrorCount = 0;
/**
* 是否锁定(0,未锁定,1、锁定)
*/
private Integer isLocked = 0;
/**
* 管理员是否更改过密码(0,未更改,1、更改)
*/
private Integer isUpdatePassword;
/**
* 删除标志
*/
@Column
private Integer delFlag = 1;
public Long getUserid() {
return userid;
}
public void setUserid(Long userid) {
this.userid = userid;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public Integer getIsInner() {
return isInner;
}
public void setIsInner(Integer isInner) {
this.isInner = isInner;
}
public Date getCreatTime() {
return creatTime;
}
public void setCreatTime(Date creatTime) {
this.creatTime = creatTime;
}
public Date getLoginTime() {
return loginTime;
}
public void setLoginTime(Date loginTime) {
this.loginTime = loginTime;
}
public Date getLastLoginTime() {
return lastLoginTime;
}
public void setLastLoginTime(Date lastLoginTime) {
this.lastLoginTime = lastLoginTime;
}
public Date getLastLoginErrorTime() {
return lastLoginErrorTime;
}
public void setLastLoginErrorTime(Date lastLoginErrorTime) {
this.lastLoginErrorTime = lastLoginErrorTime;
}
public Integer getLoginErrorCount() {
return loginErrorCount;
}
public void setLoginErrorCount(Integer loginErrorCount) {
this.loginErrorCount = loginErrorCount;
}
public Integer getIsLocked() {
return isLocked;
}
public void setIsLocked(Integer isLocked) {
this.isLocked = isLocked;
}
public Integer getIsUpdatePassword() {
return isUpdatePassword;
}
public void setIsUpdatePassword(Integer isUpdatePassword) {
this.isUpdatePassword = isUpdatePassword;
}
public Integer getDelFlag() {
return delFlag;
}
public void setDelFlag(Integer delFlag) {
this.delFlag = delFlag;
}
}
最后写根据username查找用户方法即可 Dao层
import com.trgis.firstproject.modules.sys.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
/**
* @author ZHAO
* @date 2019/1/11 18:17
*/
@Repository
public interface UserDao extends JpaRepository<User, Long>,JpaSpecificationExecutor<User> {
@Query(value="SELECT * from users where account = ?1", nativeQuery = true)
User findByAccount(String username);
}