引言:shiro是apache出的一个安全框架
废话不说,上代码,注释很详细
一、maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.2.5</version>
</dependency>
二、自定义realm继承AuthorizingRealm
public class CustomRealm extends AuthorizingRealm {
/**
* 授权用户权限
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = (String) principals.getPrimaryPrincipal();
// 获取用户
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// 获取用户角色,实际项目从数据库查询
Set<String> roleSet = new HashSet<String>();
roleSet.add("admin");
info.addRoles(roleSet);
// 获取用户权限,实际项目从数据库查询
Set<String> permissionSet = new HashSet<String>();
permissionSet.add("user:add");
permissionSet.add("user:find");
info.addStringPermissions(permissionSet);
return info;
}
/**
* 认证-登录
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
throws AuthenticationException {
if (authenticationToken.getPrincipal() == null) {
return null;
}
// 1、从主体传过来的认证信息中,获得用户名
String username = authenticationToken.getPrincipal().toString();
User user = userMapper.findByuserName(username);
return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
}
三、配置shiro
@Configuration
public class ShiroConfig {
/**
* ShiroFilterFactoryBean 处理拦截资源文件问题。
* 注意:单独一个ShiroFilterFactoryBean配置是或报错的,因为在
* 初始化ShiroFilterFactoryBean的时候需要注入:SecurityManager Filter Chain定义说明
*
*/
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
// 设置securityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 登录的url
shiroFilterFactoryBean.setLoginUrl("/login");
// 登录成功后跳转的url
shiroFilterFactoryBean.setSuccessUrl("/index");
// 未授权url
shiroFilterFactoryBean.setUnauthorizedUrl("/403");
LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// 定义filterChain,静态资源不拦截
filterChainDefinitionMap.put("/css/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/fonts/**", "anon");
filterChainDefinitionMap.put("/img/**", "anon");
// 配置退出过滤器,其中具体的退出代码Shiro已经替我们实现了
filterChainDefinitionMap.put("/logout", "logout");
// 记得登录的接口也不需要拦截
filterChainDefinitionMap.put("/submitLogin", "anon");
// 除上以外所有url都必须认证通过才可以访问,未通过认证自动跳转到LoginUrl
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public SecurityManager securityManager() {
DefaultSecurityManager securityManager = new DefaultWebSecurityManager();
// 设置realm.
securityManager.setRealm(shiroRealm());
// 注入缓存管理器,这里暂时先不用
// securityManager.setCacheManager(ehCacheManager());
// 注入记住我管理器,这里暂时先不用
// securityManager.setRememberMeManager(rememberMeManager());
return securityManager;
}
@Bean
public CustomRealm shiroRealm() {
return new CustomRealm();//上面自定义的Realm
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
//这段代码为了支持shiro注解
@Bean
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator app = new DefaultAdvisorAutoProxyCreator();
app.setProxyTargetClass(true);
return app;
}
}
四、controller
返回的视图就不贴了
@Controller
public class HomeController {
@GetMapping("/")
public String loginpage(ModelMap modelMap) {
return "login";
}
@RequestMapping("/login")
public String login(ModelMap modelMap, User user) {
// 添加用户认证信息
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(user.getUserName(), user.getPassword());
// 进行验证,这里可以捕获异常,然后返回对应信息
try {
subject.login(usernamePasswordToken);
} catch (Exception e) {
return "login";
}
return "index";
}
// 登出
@RequestMapping(value = "/logout")
public String logout() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "login";
}
@RequestMapping(value = "/index")
public String index() {
return "index";
}
/**
*
* 注解表示拥有“user:add”权限才能访问,接收的是一个String数组
* 如果是一个数组,默认表示拥有这个数组全部权限才能访问接口
**/
@RequiresPermissions({ "user:add" })
@RequestMapping(value = "/add")
public String test() {
return "test";
}
/**
*
* 与上述相似,不同的是需要拥有这个角色才能访问
* 第二个参数logical(可选值AND、OR):默认为AND表示需要全部角色,
* 为OR不难理解拥有其中一个角色就行。
* 上述的@RequiresPermissions注解logical参数也适用
**/
@RequiresRoles(value = { "admin","user" }, logical = Logical.OR)
@RequestMapping(value = "/find")
public String test1() {
return "test";
}
}
到这里就整合完毕了,欢迎大家相互交流。
向上的路并不拥挤,而大多数人选择了安逸——it疯子也